Skip to content

Commit a52d75f

Browse files
committed
Merge branch 'release/1.0.0-alpha.7'
2 parents 3c4491d + 0cf0d11 commit a52d75f

14 files changed

+96
-29
lines changed

CHANGELOG.md

+10
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66

77
## [Unreleased]
88

9+
## [v1.0.0-alpha.7](https://github.com/studiometa/ui/compare/1.0.0-alpha.6..1.0.0-alpha.7) (2024-09-10)
10+
11+
### Fixed
12+
13+
- **DataBind:** fix inconsistencies with removed DOM elements ([#293](https://github.com/studiometa/ui/issues/293), [#294](https://github.com/studiometa/ui/pull/294), [de945b1](https://github.com/studiometa/ui/commit/de945b1))
14+
15+
### Changed
16+
17+
- Update @studiometa/js-toolkit 3.0.0-alpha.9 → 3.0.0-alpha.10 ([3adbebc](https://github.com/studiometa/ui/commit/3adbebc))
18+
919
## [v1.0.0-alpha.6](https://github.com/studiometa/ui/compare/1.0.0-alpha.5..1.0.0-alpha.6) (2024-08-27)
1020

1121
### Added

composer.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "studiometa/ui",
3-
"version": "1.0.0-alpha.6",
3+
"version": "1.0.0-alpha.7",
44
"description": "A set of opiniated, unstyled and accessible components.",
55
"license": "MIT",
66
"require": {

package-lock.json

+11-11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@studiometa/ui-workspace",
3-
"version": "1.0.0-alpha.6",
3+
"version": "1.0.0-alpha.7",
44
"private": true,
55
"workspaces": [
66
"packages/*"

packages/docs/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@studiometa/ui-docs",
3-
"version": "1.0.0-alpha.6",
3+
"version": "1.0.0-alpha.7",
44
"private": true,
55
"type": "module",
66
"scripts": {
@@ -11,7 +11,7 @@
1111
"build": "vitepress build ."
1212
},
1313
"dependencies": {
14-
"@studiometa/js-toolkit": "^3.0.0-alpha.9"
14+
"@studiometa/js-toolkit": "^3.0.0-alpha.10"
1515
},
1616
"devDependencies": {
1717
"@iconify-json/octicon": "1.1.56",

packages/playground/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@studiometa/ui-playground",
3-
"version": "1.0.0-alpha.6",
3+
"version": "1.0.0-alpha.7",
44
"private": true,
55
"type": "module",
66
"scripts": {

packages/tests/__utils__/h.ts

+15
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,18 @@ export function h<T extends keyof HTMLElementTagNameMap = 'div'>(
3232

3333
return el;
3434
}
35+
36+
/**
37+
* Connect the given element to a document instance in order
38+
* to set its `isConnected` property to `true`.
39+
*/
40+
export function connectElement<T extends Node>(element:T):T {
41+
const doc = new Document();
42+
doc.append(element);
43+
return element;
44+
}
45+
46+
/**
47+
* Create an HTMLElement and connect it to a document.
48+
*/
49+
export const hConnected: typeof h = (...args) => connectElement(h(...args));

packages/tests/atoms/DataBind.spec.ts

+41-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { it, describe, expect, vi } from 'vitest';
22
import { DataBind, DataComputed, DataEffect } from '@studiometa/ui';
3-
import { destroy, h, mount } from '#test-utils';
3+
import { destroy, hConnected as h, mount } from '#test-utils';
44

55
describe('The DataBind component', () => {
66
it('should set the textContent of the root element', () => {
@@ -151,8 +151,12 @@ describe('The DataBind component', () => {
151151
it('should dispatch value to other instances', async () => {
152152
const instance1 = new DataBind(h('div', { dataOptionName: 'a' }, ['foo']));
153153
const instance2 = new DataBind(h('div', { dataOptionName: 'a' }, ['foo']));
154-
const instance3 = new DataComputed(h('div', { dataOptionName: 'a', dataOptionCompute: 'value + value' }, ['foofoo']));
155-
const instance4 = new DataEffect(h('div', { dataOptionName: 'a', dataOptionEffect: 'target.id = value', id: 'foo' }));
154+
const instance3 = new DataComputed(
155+
h('div', { dataOptionName: 'a', dataOptionCompute: 'value + value' }, ['foofoo']),
156+
);
157+
const instance4 = new DataEffect(
158+
h('div', { dataOptionName: 'a', dataOptionEffect: 'target.id = value', id: 'foo' }),
159+
);
156160

157161
await mount(instance1, instance2, instance3, instance4);
158162

@@ -166,4 +170,38 @@ describe('The DataBind component', () => {
166170
expect(instance3.value).toBe('barbar');
167171
expect(instance4.$el.id).toBe('bar');
168172
});
173+
174+
it('should forget related instances not in the DOM anymore', async () => {
175+
const fragment = new Document();
176+
const inputA = h('input', {
177+
type: 'checkbox',
178+
value: 'foo',
179+
checked: '',
180+
dataOptionName: 'checkbox[]',
181+
});
182+
const inputB = h('input', {
183+
type: 'checkbox',
184+
value: 'bar',
185+
checked: '',
186+
dataOptionName: 'checkbox[]',
187+
});
188+
fragment.append(inputA, inputB);
189+
190+
const instanceA = new DataBind(inputA);
191+
const instanceB = new DataBind(inputB);
192+
193+
await mount(instanceA, instanceB);
194+
195+
expect(inputA.isConnected).toBe(true);
196+
expect(inputB.isConnected).toBe(true);
197+
expect(instanceA.value).toEqual(['foo', 'bar']);
198+
199+
inputB.replaceWith(
200+
h('input', { type: 'checkbox', value: 'bar', dataOptionName: 'checkbox[]' }),
201+
);
202+
203+
expect(inputA.isConnected).toBe(true);
204+
expect(inputB.isConnected).toBe(false);
205+
expect(instanceA.value).toEqual(['foo']);
206+
});
169207
});

packages/tests/atoms/DataComputed.spec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { it, describe, expect, vi } from 'vitest';
22
import { Base } from '@studiometa/js-toolkit';
33
import { DataComputed } from '@studiometa/ui';
4-
import { h } from '#test-utils';
4+
import { hConnected as h, } from '#test-utils';
55

66
describe('The DataModel component', () => {
77
it('should set the value as the returned value from the compute option', () => {

packages/tests/atoms/DataEffect.spec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { it, describe, expect, vi } from 'vitest';
22
import { Base } from '@studiometa/js-toolkit';
33
import { DataEffect } from '@studiometa/ui';
4-
import { h } from '#test-utils';
4+
import { hConnected as h } from '#test-utils';
55

66
describe('The DataModel component', () => {
77
it('should execute the compute option without setting a value', () => {

packages/tests/atoms/DataModel.spec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { it, describe, expect } from 'vitest';
22
import { DataModel } from '@studiometa/ui';
3-
import { h, mount } from '#test-utils';
3+
import { hConnected as h, mount } from '#test-utils';
44

55
function check(input: HTMLInputElement, checked = true) {
66
input.checked = checked;

packages/tests/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@studiometa/ui-tests",
3-
"version": "1.0.0-alpha.6",
3+
"version": "1.0.0-alpha.7",
44
"private": true,
55
"type": "module",
66
"scripts": {

packages/ui/atoms/Data/DataBind.ts

+8-4
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type { BaseConfig, BaseProps } from '@studiometa/js-toolkit';
33
import { isArray } from '@studiometa/js-toolkit/utils';
44
import { isInput, isCheckbox, isSelect } from './utils.js';
55

6-
const instances = new Map<string, Set<DataBind>>();
6+
const groups = new Map<string, Set<DataBind>>();
77

88
export interface DataBindProps extends BaseProps {
99
$options: {
@@ -24,11 +24,15 @@ export class DataBind<T extends BaseProps = BaseProps> extends Base<DataBindProp
2424
get relatedInstances() {
2525
const { name } = this.$options;
2626

27-
if (!instances.has(name)) {
28-
instances.set(name, new Set());
27+
const instances = groups.get(name) ?? groups.set(name, new Set()).get(name);
28+
29+
for (const instance of instances) {
30+
if (!instance.$el.isConnected) {
31+
instances.delete(instance);
32+
}
2933
}
3034

31-
return instances.get(name);
35+
return instances;
3236
}
3337

3438
get multiple() {

packages/ui/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@studiometa/ui",
3-
"version": "1.0.0-alpha.6",
3+
"version": "1.0.0-alpha.7",
44
"description": "A set of opiniated, unstyled and accessible components",
55
"publishConfig": {
66
"access": "public"
@@ -29,7 +29,7 @@
2929
},
3030
"homepage": "https://github.com/studiometa/ui#readme",
3131
"dependencies": {
32-
"@studiometa/js-toolkit": "^3.0.0-alpha.9",
32+
"@studiometa/js-toolkit": "^3.0.0-alpha.10",
3333
"deepmerge": "^4.3.1"
3434
}
3535
}

0 commit comments

Comments
 (0)