@neovici/cosmoz-form 3.5.0 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/add/render.d.ts +16 -3
- package/dist/add/render.d.ts.map +1 -1
- package/dist/add/render.js +9 -6
- package/dist/add/styles.d.ts.map +1 -1
- package/dist/add/styles.js +13 -25
- package/dist/form-dialog/form-dialog.d.ts +2 -1
- package/dist/form-dialog/form-dialog.d.ts.map +1 -1
- package/dist/form-dialog/form-dialog.js +12 -5
- package/dist/form-dialog/style.css.d.ts.map +1 -1
- package/dist/form-dialog/style.css.js +16 -28
- package/dist/inputs/autocomplete.d.ts +3 -0
- package/dist/inputs/autocomplete.d.ts.map +1 -1
- package/dist/inputs/autocomplete.js +5 -5
- package/dist/inputs/base.d.ts +1 -0
- package/dist/inputs/base.d.ts.map +1 -1
- package/dist/inputs/base.js +2 -7
- package/dist/inputs/common.d.ts +2 -2
- package/dist/inputs/common.d.ts.map +1 -1
- package/dist/inputs/common.js +5 -5
- package/dist/inputs/date-range.d.ts.map +1 -1
- package/dist/inputs/date-range.js +3 -1
- package/dist/inputs/inline-file.d.ts.map +1 -1
- package/dist/inputs/inline-file.js +8 -23
- package/dist/inputs/read-only-number.d.ts.map +1 -1
- package/dist/inputs/read-only-number.js +2 -2
- package/dist/inputs/render.d.ts +3 -3
- package/dist/inputs/render.d.ts.map +1 -1
- package/dist/inputs/render.js +5 -5
- package/dist/render/items.d.ts.map +1 -1
- package/dist/render/items.js +8 -3
- package/dist/render/styles.d.ts.map +1 -1
- package/dist/render/styles.js +16 -33
- package/dist/styles/button.d.ts.map +1 -1
- package/dist/styles/button.js +17 -31
- package/dist/test/form-dialog.test.d.ts +2 -0
- package/dist/test/form-dialog.test.d.ts.map +1 -0
- package/dist/test/form-dialog.test.js +64 -0
- package/dist/types/index.d.ts +3 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/use-async-form-core.d.ts.map +1 -1
- package/dist/use-async-form-core.js +15 -10
- package/dist/use-items/use-async-rules.d.ts.map +1 -1
- package/dist/use-items/use-async-rules.js +18 -13
- package/package.json +10 -10
- package/dist/controls/cz-toggle.d.ts +0 -2
- package/dist/controls/cz-toggle.d.ts.map +0 -1
- package/dist/controls/cz-toggle.js +0 -40
- package/dist/styles/toggle.d.ts +0 -3
- package/dist/styles/toggle.d.ts.map +0 -1
- package/dist/styles/toggle.js +0 -46
package/dist/render/styles.js
CHANGED
|
@@ -2,15 +2,17 @@ import { tagged as css } from '@neovici/cosmoz-utils';
|
|
|
2
2
|
export const styles = css `
|
|
3
3
|
.headers {
|
|
4
4
|
display: flex;
|
|
5
|
-
border-bottom: solid 1px
|
|
6
|
-
font-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
border-bottom: solid 1px var(--cz-color-border-primary);
|
|
6
|
+
font-size: var(--cz-text-base);
|
|
7
|
+
line-height: var(--cz-text-base-line-height);
|
|
8
|
+
font-weight: var(--cz-font-weight-regular);
|
|
9
|
+
color: var(--cz-color-text-secondary);
|
|
10
|
+
padding-block: calc(var(--cz-spacing) * 2.5);
|
|
9
11
|
width: 100%;
|
|
10
12
|
}
|
|
11
13
|
.header {
|
|
12
14
|
flex: auto;
|
|
13
|
-
margin:
|
|
15
|
+
margin-inline: var(--cz-spacing);
|
|
14
16
|
flex: 1 1 0px;
|
|
15
17
|
}
|
|
16
18
|
.items {
|
|
@@ -28,44 +30,25 @@ export const styles = css `
|
|
|
28
30
|
flex: 1 1 0px;
|
|
29
31
|
}
|
|
30
32
|
.item > .input {
|
|
31
|
-
margin:
|
|
32
|
-
}
|
|
33
|
-
.item cosmoz-input::part(error),
|
|
34
|
-
.item cosmoz-autocomplete::part(input-error) {
|
|
35
|
-
position: static;
|
|
36
|
-
margin-bottom: -10px;
|
|
33
|
+
margin: var(--cz-spacing);
|
|
37
34
|
}
|
|
35
|
+
|
|
38
36
|
.input-basic {
|
|
39
|
-
font-size:
|
|
40
|
-
line-height:
|
|
41
|
-
border-bottom: 2px solid var(--
|
|
42
|
-
margin:
|
|
37
|
+
font-size: var(--cz-text-base);
|
|
38
|
+
line-height: var(--cz-text-base-line-height);
|
|
39
|
+
border-bottom: 2px solid var(--cz-color-border-primary);
|
|
40
|
+
margin: var(--cz-spacing);
|
|
43
41
|
}
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
cosmoz-button {
|
|
43
|
+
margin-inline: var(--cz-spacing);
|
|
46
44
|
align-items: center;
|
|
47
|
-
justify-content: center;
|
|
48
|
-
background: none;
|
|
49
|
-
border: none;
|
|
50
|
-
outline: none;
|
|
51
|
-
cursor: pointer;
|
|
52
|
-
width: 24px;
|
|
53
|
-
height: 24px;
|
|
54
|
-
align-self: center;
|
|
55
|
-
flex: none;
|
|
56
|
-
margin: 0 8px;
|
|
57
|
-
padding: 0;
|
|
58
|
-
}
|
|
59
|
-
.remove[disabled] {
|
|
60
|
-
opacity: 0;
|
|
61
|
-
pointer-events: none;
|
|
62
45
|
}
|
|
63
46
|
/* Empty stand-in matching the remove button's footprint, so rows without a
|
|
64
47
|
remove button (the header row and the add row) keep their columns aligned
|
|
65
48
|
with the removable rows. */
|
|
66
49
|
.remove-placeholder {
|
|
67
50
|
flex: none;
|
|
68
|
-
width:
|
|
51
|
+
width: 36px;
|
|
69
52
|
margin: 0 8px;
|
|
70
53
|
}
|
|
71
54
|
`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../src/styles/button.ts"],"names":[],"mappings":";AAEA,
|
|
1
|
+
{"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../src/styles/button.ts"],"names":[],"mappings":";AAEA,wBAoFE"}
|
package/dist/styles/button.js
CHANGED
|
@@ -1,56 +1,42 @@
|
|
|
1
1
|
import { tagged as css } from '@neovici/cosmoz-utils';
|
|
2
2
|
export default css `
|
|
3
|
-
.button {
|
|
4
|
-
font-family: inherit;
|
|
5
|
-
}
|
|
6
|
-
.button:not([slot='bottom-bar-menu']),
|
|
7
3
|
.file::-webkit-file-upload-button,
|
|
8
4
|
.file::file-selector-button {
|
|
9
|
-
background: var(--
|
|
10
|
-
color: var(--
|
|
5
|
+
background: var(--cz-color-bg-overlay);
|
|
6
|
+
color: var(--cz-color-text-on-brand);
|
|
11
7
|
box-sizing: border-box;
|
|
12
8
|
cursor: pointer;
|
|
13
9
|
outline: none;
|
|
14
10
|
flex: none;
|
|
15
11
|
border: none;
|
|
16
|
-
padding:
|
|
17
|
-
border-radius:
|
|
12
|
+
padding-inline: calc(var(--cz-spacing) * 4);
|
|
13
|
+
border-radius: var(--cz-radius-md);
|
|
18
14
|
min-height: 40px;
|
|
19
15
|
min-width: 78px;
|
|
20
16
|
font-family: inherit;
|
|
21
|
-
font-size:
|
|
22
|
-
|
|
23
|
-
|
|
17
|
+
font-size: var(--cz-text-sm);
|
|
18
|
+
line-height: var(--cz-text-sm-line-height);
|
|
19
|
+
font-weight: var(--cz-font-weight-medium);
|
|
24
20
|
text-overflow: ellipsis;
|
|
25
21
|
white-space: nowrap;
|
|
26
22
|
}
|
|
27
|
-
|
|
28
|
-
.button:not([slot='bottom-bar-menu']):active,
|
|
23
|
+
|
|
29
24
|
.file::-webkit-file-upload-button:hover,
|
|
30
25
|
.file::file-selector-button:hover {
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
.button[disabled],
|
|
34
|
-
.button:disabled {
|
|
35
|
-
opacity: var(--cosmoz-button-disabled-opacity, 0.15);
|
|
36
|
-
pointer-events: none;
|
|
37
|
-
}
|
|
38
|
-
.button:active {
|
|
39
|
-
background: hsl(
|
|
40
|
-
from var(--cosmoz-button-hover-bg-color, #3a3f44) h s calc(l + 10)
|
|
41
|
-
);
|
|
42
|
-
}
|
|
43
|
-
a.button {
|
|
44
|
-
text-decoration: none;
|
|
26
|
+
opacity: 0.8;
|
|
45
27
|
}
|
|
28
|
+
|
|
46
29
|
.buttons {
|
|
47
30
|
display: flex;
|
|
48
31
|
justify-content: flex-end;
|
|
49
|
-
padding:
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
32
|
+
padding-block: calc(var(--cz-spacing) * 5.5);
|
|
33
|
+
gap: calc(var(--cz-spacing) * 2);
|
|
34
|
+
|
|
35
|
+
& cosmoz-button {
|
|
36
|
+
flex: 1;
|
|
37
|
+
}
|
|
53
38
|
}
|
|
39
|
+
|
|
54
40
|
.button-ricon {
|
|
55
41
|
border: none;
|
|
56
42
|
border-radius: 50%;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"form-dialog.test.d.ts","sourceRoot":"","sources":["../../src/test/form-dialog.test.ts"],"names":[],"mappings":"AAGA,OAAO,+BAA+B,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { assert, fixture, waitUntil } from '@open-wc/testing';
|
|
2
|
+
import { html } from 'lit-html';
|
|
3
|
+
import '../form-dialog/form-dialog.js';
|
|
4
|
+
// design tokens the alert-card chrome relies on; applied via inline style on
|
|
5
|
+
// the host so they inherit into its shadow root (the app loads them globally)
|
|
6
|
+
const tokenStyle = '--cz-color-bg-error: #fef3f2; --cz-color-border-error-subtle: #fda29b; --cz-radius-lg: 0.625rem; --cz-spacing: 0.25rem; --cz-color-text-error: #d92d20;';
|
|
7
|
+
const LONG_ERROR = Array.from({ length: 8 }, (_, i) => `Row ${1078 + i}: Category 'Sheeeesh' is not valid.`).join(' ');
|
|
8
|
+
const openFailingDialog = async (onSave) => {
|
|
9
|
+
const el = (await fixture(html `
|
|
10
|
+
<cosmoz-form-dialog
|
|
11
|
+
heading="Test"
|
|
12
|
+
style=${tokenStyle}
|
|
13
|
+
.fields=${[]}
|
|
14
|
+
.initial=${{}}
|
|
15
|
+
.onSave=${onSave}
|
|
16
|
+
></cosmoz-form-dialog>
|
|
17
|
+
`));
|
|
18
|
+
const root = el.shadowRoot;
|
|
19
|
+
const save = root.querySelector('.buttons .save');
|
|
20
|
+
assert.ok(save, 'save button rendered');
|
|
21
|
+
save.click();
|
|
22
|
+
await waitUntil(() => root.querySelector('.failure') != null);
|
|
23
|
+
return { el, root };
|
|
24
|
+
};
|
|
25
|
+
suite('cosmoz-form-dialog failure rendering', () => {
|
|
26
|
+
test('failure renders above the footer, not inside the buttons row', async () => {
|
|
27
|
+
const { root } = await openFailingDialog(() => Promise.reject(new Error('Short failure')));
|
|
28
|
+
const failure = root.querySelector('.failure'), buttons = root.querySelector('.buttons');
|
|
29
|
+
assert.include(failure.textContent ?? '', 'Short failure');
|
|
30
|
+
assert.isNull(buttons.querySelector('.failure'), 'footer must contain only buttons');
|
|
31
|
+
assert.isTrue(failure.compareDocumentPosition(buttons) ===
|
|
32
|
+
Node.DOCUMENT_POSITION_FOLLOWING, 'failure block precedes the footer');
|
|
33
|
+
});
|
|
34
|
+
test('long failure is capped and scrollable', async () => {
|
|
35
|
+
const { root } = await openFailingDialog(() => Promise.reject(new Error(LONG_ERROR)));
|
|
36
|
+
const failure = root.querySelector('.failure');
|
|
37
|
+
const style = getComputedStyle(failure);
|
|
38
|
+
assert.equal(style.overflowY, 'auto');
|
|
39
|
+
// 40vh resolves to a px value; assert it is a bounded, finite cap
|
|
40
|
+
assert.isTrue(style.maxHeight.endsWith('px'));
|
|
41
|
+
assert.isBelow(Number.parseFloat(style.maxHeight), 500);
|
|
42
|
+
assert.equal(style.whiteSpace, 'pre-wrap');
|
|
43
|
+
});
|
|
44
|
+
test('failure renders as an error alert card', async () => {
|
|
45
|
+
const { root } = await openFailingDialog(() => Promise.reject(new Error(LONG_ERROR)));
|
|
46
|
+
const style = getComputedStyle(root.querySelector('.failure'));
|
|
47
|
+
assert.notEqual(style.backgroundColor, 'rgba(0, 0, 0, 0)', 'has a tinted background');
|
|
48
|
+
assert.notEqual(style.borderWidth, '0px', 'has a border');
|
|
49
|
+
assert.notEqual(style.borderRadius, '0px', 'is rounded');
|
|
50
|
+
});
|
|
51
|
+
test('rich failure content (e.content) renders instead of the message', async () => {
|
|
52
|
+
const { root } = await openFailingDialog(() => {
|
|
53
|
+
const err = new Error('The file contains 3 errors');
|
|
54
|
+
err.content = html `
|
|
55
|
+
<div><b>The file contains 3 errors</b></div>
|
|
56
|
+
<div name="row-1">Row 1078: Category 'Sheeeesh' is not valid.</div>
|
|
57
|
+
`;
|
|
58
|
+
return Promise.reject(err);
|
|
59
|
+
});
|
|
60
|
+
const failure = root.querySelector('.failure');
|
|
61
|
+
assert.equal(failure.querySelector('b')?.textContent, 'The file contains 3 errors');
|
|
62
|
+
assert.include(failure.querySelector('[name="row-1"]')?.textContent ?? '', 'Row 1078: Category \'Sheeeesh\' is not valid.');
|
|
63
|
+
});
|
|
64
|
+
});
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { DatepickerMode } from '@neovici/cosmoz-datepicker';
|
|
1
2
|
import { AutocompleteProps, CommonFieldProps, FileProps, TextareaProps } from '../inputs';
|
|
2
3
|
import { DatepickerProps } from '../inputs/datepicker';
|
|
3
4
|
import { ReadOnlyNumberProps } from '../inputs/read-only-number';
|
|
@@ -31,14 +32,14 @@ export type Codec<T extends object, K extends keyof T, V extends T[K], C extends
|
|
|
31
32
|
Invoked<T, Field<T, K, V, C>, V, unknown, C>,
|
|
32
33
|
Invoked<T, Field<T, K, V, C>, unknown, V, C>
|
|
33
34
|
];
|
|
34
|
-
export interface Field<T extends object, K extends keyof T, V extends T[K] = T[K], C extends object = object> extends CommonFieldProps<T, K, V, C>, TextareaProps, AutocompleteProps<T, K, V, C>, FileProps<T, K, V>, DatepickerProps, ReadOnlyNumberProps {
|
|
35
|
+
export interface Field<T extends object, K extends keyof T, V extends T[K] = T[K], C extends object = object> extends CommonFieldProps<T, K, V, C>, TextareaProps, Omit<AutocompleteProps<T, K, V, C>, 'mode'>, FileProps<T, K, V>, Omit<DatepickerProps, 'mode'>, ReadOnlyNumberProps {
|
|
36
|
+
mode?: 'select' | DatepickerMode;
|
|
35
37
|
id: K;
|
|
36
38
|
path?: keyof T;
|
|
37
39
|
label?: Invokable<T, Field<T, K, V, C>, V, string, C>;
|
|
38
40
|
description?: string;
|
|
39
41
|
placeholder?: Invokable<T, Field<T, K, V, C>, V, string, C>;
|
|
40
42
|
validate?: Validate<T, K, V, C>;
|
|
41
|
-
mandatory?: Invokable<T, Field<T, K, V, C>, V, boolean, C>;
|
|
42
43
|
disabled?: Invokable<T, Field<T, K, V, C>, V, boolean, C>;
|
|
43
44
|
hidden?: Invokable<T, Field<T, K, V, C>, V, boolean, C>;
|
|
44
45
|
warning?: Invokable<T, Field<T, K, V, C>, V, Renderable, C>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-async-form-core.d.ts","sourceRoot":"","sources":["../src/use-async-form-core.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAe,MAAM,cAAc,CAAC;AAE/D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAU/C;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,gBAAgB,GAAI,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,MAAM,GAAG,MAAM,EAC3E,MAAM,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,EACnB,YAAY,SAAS,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,SAAS,EACtD,OAAO;IAAE,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,IAAI,CAAA;CAAE,KACpE,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG;IAAE,UAAU,EAAE,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"use-async-form-core.d.ts","sourceRoot":"","sources":["../src/use-async-form-core.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAe,MAAM,cAAc,CAAC;AAE/D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAU/C;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,gBAAgB,GAAI,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,MAAM,GAAG,MAAM,EAC3E,MAAM,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,EACnB,YAAY,SAAS,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,SAAS,EACtD,OAAO;IAAE,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,IAAI,CAAA;CAAE,KACpE,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG;IAAE,UAAU,EAAE,OAAO,CAAA;CA+EvC,CAAC"}
|
|
@@ -27,9 +27,14 @@ export const useAsyncFormCore = (form, asyncRules, opts) => {
|
|
|
27
27
|
// processing state is updated only on 0→1 and 1→0 transitions.
|
|
28
28
|
const pendingCount = useRef(0);
|
|
29
29
|
const [processing, setProcessing] = useState(false);
|
|
30
|
+
// Refs are initialized synchronously, so `.current` is defined for the
|
|
31
|
+
// lifetime of the hook; pion's Ref typing models lazy initialization.
|
|
32
|
+
const runners = runnersRef;
|
|
33
|
+
const prevDeps = prevDepsRef;
|
|
34
|
+
const pending = pendingCount;
|
|
30
35
|
// Cleanup: cancel all in-flight rules on unmount
|
|
31
36
|
useEffect(() => () => {
|
|
32
|
-
for (const runner of
|
|
37
|
+
for (const runner of runners.current.values())
|
|
33
38
|
runner.cancel();
|
|
34
39
|
}, []);
|
|
35
40
|
// Dep-check + rule dispatch: runs after every values or context change
|
|
@@ -39,19 +44,19 @@ export const useAsyncFormCore = (form, asyncRules, opts) => {
|
|
|
39
44
|
const context = form.context;
|
|
40
45
|
for (const rule of asyncRules) {
|
|
41
46
|
const [ruleFn, depsFn, runnerFactory = makeTakeLatestRunner] = rule;
|
|
42
|
-
if (!
|
|
43
|
-
|
|
47
|
+
if (!runners.current.has(rule)) {
|
|
48
|
+
runners.current.set(rule, runnerFactory());
|
|
44
49
|
}
|
|
45
50
|
const deps = depsFn(form.values, undefined, context);
|
|
46
|
-
const prev =
|
|
51
|
+
const prev = prevDeps.current.get(rule);
|
|
47
52
|
// Skip if deps unchanged (Object.is per element, same as applyRules)
|
|
48
53
|
if (prev != null && !changed(deps, prev)) {
|
|
49
54
|
continue;
|
|
50
55
|
}
|
|
51
|
-
|
|
52
|
-
const runner =
|
|
53
|
-
|
|
54
|
-
if (
|
|
56
|
+
prevDeps.current.set(rule, deps);
|
|
57
|
+
const runner = runners.current.get(rule);
|
|
58
|
+
pending.current++;
|
|
59
|
+
if (pending.current === 1)
|
|
55
60
|
setProcessing(true);
|
|
56
61
|
runner
|
|
57
62
|
.run(ruleFn, form.values, (patch) => form.onChange(patch, false), // intermediate: no touch
|
|
@@ -63,8 +68,8 @@ export const useAsyncFormCore = (form, asyncRules, opts) => {
|
|
|
63
68
|
})
|
|
64
69
|
.catch((err) => onError(err, rule))
|
|
65
70
|
.finally(() => {
|
|
66
|
-
|
|
67
|
-
if (
|
|
71
|
+
pending.current--;
|
|
72
|
+
if (pending.current === 0)
|
|
68
73
|
setProcessing(false);
|
|
69
74
|
});
|
|
70
75
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-async-rules.d.ts","sourceRoot":"","sources":["../../src/use-items/use-async-rules.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAe,MAAM,eAAe,CAAC;AAEhE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AA6BhD;;;;;;;;GAQG;AACH,eAAO,MAAM,aAAa,GAAI,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,MAAM,GAAG,MAAM,EACxE,OAAO,CAAC,EAAE,EACV,YAAY,SAAS,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,SAAS,EACtD,QAAQ,YAAY,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,EACjC,OAAO;IACN,OAAO,CAAC,EAAE,CAAC,CAAC;IACZ,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3E,KACC;IAAE,UAAU,EAAE,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"use-async-rules.d.ts","sourceRoot":"","sources":["../../src/use-items/use-async-rules.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAe,MAAM,eAAe,CAAC;AAEhE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AA6BhD;;;;;;;;GAQG;AACH,eAAO,MAAM,aAAa,GAAI,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,MAAM,GAAG,MAAM,EACxE,OAAO,CAAC,EAAE,EACV,YAAY,SAAS,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,SAAS,EACtD,QAAQ,YAAY,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,EACjC,OAAO;IACN,OAAO,CAAC,EAAE,CAAC,CAAC;IACZ,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3E,KACC;IAAE,UAAU,EAAE,OAAO,CAAA;CAiFvB,CAAC"}
|
|
@@ -5,11 +5,11 @@ const DEFAULT_ON_ERROR = (err) => {
|
|
|
5
5
|
// eslint-disable-next-line no-console
|
|
6
6
|
console.error('[cosmoz-form] async rule error:', err);
|
|
7
7
|
};
|
|
8
|
-
const ensureRuleTracking = (rule,
|
|
9
|
-
if (
|
|
8
|
+
const ensureRuleTracking = (rule, runners, prevDeps) => {
|
|
9
|
+
if (runners.current.has(rule))
|
|
10
10
|
return;
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
runners.current.set(rule, new Map());
|
|
12
|
+
prevDeps.current.set(rule, new Map());
|
|
13
13
|
};
|
|
14
14
|
/**
|
|
15
15
|
* Composes with useItemsCore / useItems to add async rules.
|
|
@@ -27,9 +27,14 @@ export const useAsyncRules = (items, asyncRules, update, opts) => {
|
|
|
27
27
|
const [processing, setProcessing] = useState(false);
|
|
28
28
|
const runnersRef = useRef(new Map());
|
|
29
29
|
const prevDepsRef = useRef(new Map());
|
|
30
|
+
// Refs are initialized synchronously, so `.current` is defined for the
|
|
31
|
+
// lifetime of the hook; pion's Ref typing models lazy initialization.
|
|
32
|
+
const runners = runnersRef;
|
|
33
|
+
const prevDeps = prevDepsRef;
|
|
34
|
+
const pending = pendingCount;
|
|
30
35
|
// Cleanup on unmount
|
|
31
36
|
useEffect(() => () => {
|
|
32
|
-
for (const perItem of
|
|
37
|
+
for (const perItem of runners.current.values()) {
|
|
33
38
|
for (const runner of perItem.values()) {
|
|
34
39
|
runner.cancel();
|
|
35
40
|
}
|
|
@@ -42,21 +47,21 @@ export const useAsyncRules = (items, asyncRules, update, opts) => {
|
|
|
42
47
|
}
|
|
43
48
|
for (const rule of asyncRules) {
|
|
44
49
|
const [ruleFn, depsFn, runnerFactory = makeTakeLatestRunner] = rule;
|
|
45
|
-
ensureRuleTracking(rule,
|
|
50
|
+
ensureRuleTracking(rule, runners, prevDeps);
|
|
46
51
|
for (const [idx, item] of items.entries()) {
|
|
47
|
-
const runnersForRule =
|
|
52
|
+
const runnersForRule = runners.current.get(rule);
|
|
48
53
|
if (!runnersForRule.has(idx)) {
|
|
49
54
|
runnersForRule.set(idx, runnerFactory());
|
|
50
55
|
}
|
|
51
56
|
const deps = depsFn(item, idx, context);
|
|
52
|
-
const prev =
|
|
57
|
+
const prev = prevDeps.current.get(rule).get(idx);
|
|
53
58
|
if (prev != null && !changed(deps, prev)) {
|
|
54
59
|
continue;
|
|
55
60
|
}
|
|
56
|
-
|
|
61
|
+
prevDeps.current.get(rule).set(idx, deps);
|
|
57
62
|
const runner = runnersForRule.get(idx);
|
|
58
|
-
|
|
59
|
-
if (
|
|
63
|
+
pending.current++;
|
|
64
|
+
if (pending.current === 1)
|
|
60
65
|
setProcessing(true);
|
|
61
66
|
runner
|
|
62
67
|
.run(ruleFn, item, (patch) => update(idx, patch), // intermediate: no touch
|
|
@@ -68,8 +73,8 @@ export const useAsyncRules = (items, asyncRules, update, opts) => {
|
|
|
68
73
|
})
|
|
69
74
|
.catch((err) => onError(err, rule, idx))
|
|
70
75
|
.finally(() => {
|
|
71
|
-
|
|
72
|
-
if (
|
|
76
|
+
pending.current--;
|
|
77
|
+
if (pending.current === 0)
|
|
73
78
|
setProcessing(false);
|
|
74
79
|
});
|
|
75
80
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@neovici/cosmoz-form",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.1.0",
|
|
4
4
|
"description": "A pionjs component",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"web-components",
|
|
@@ -50,16 +50,19 @@
|
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
52
|
"@lit-labs/virtualizer": "^2.1.1",
|
|
53
|
-
"@neovici/cosmoz-autocomplete": "^
|
|
53
|
+
"@neovici/cosmoz-autocomplete": "^14.0.0",
|
|
54
|
+
"@neovici/cosmoz-button": "^1.1.0",
|
|
54
55
|
"@neovici/cosmoz-datepicker": "^1.0.3",
|
|
55
|
-
"@neovici/cosmoz-dialog": "^
|
|
56
|
+
"@neovici/cosmoz-dialog": "^6.0.0",
|
|
57
|
+
"@neovici/cosmoz-dropdown": "^8.0.0",
|
|
56
58
|
"@neovici/cosmoz-icons": "^1.4.0",
|
|
57
|
-
"@neovici/cosmoz-input": "^
|
|
59
|
+
"@neovici/cosmoz-input": "^6.0.0",
|
|
58
60
|
"@neovici/cosmoz-spinner": "^1.0.2",
|
|
61
|
+
"@neovici/cosmoz-tokens": "^3.4.0",
|
|
59
62
|
"@neovici/cosmoz-utils": "^6.22.0",
|
|
60
|
-
"@pionjs/pion": "^2.
|
|
63
|
+
"@pionjs/pion": "^2.13.0",
|
|
61
64
|
"date-fns": "^4.1.0",
|
|
62
|
-
"i18next": "
|
|
65
|
+
"i18next": "^26.4.2",
|
|
63
66
|
"lit-html": "^3.3.1"
|
|
64
67
|
},
|
|
65
68
|
"devDependencies": {
|
|
@@ -70,7 +73,7 @@
|
|
|
70
73
|
"@neovici/testing": "^2.0.0",
|
|
71
74
|
"@open-wc/testing": "^4.0.0",
|
|
72
75
|
"@open-wc/testing-helpers": "^3.0.1",
|
|
73
|
-
"@playwright/test": "1.60.0",
|
|
76
|
+
"@playwright/test": "^1.60.0",
|
|
74
77
|
"@storybook/addon-docs": "^10.2.17",
|
|
75
78
|
"@storybook/addon-links": "^10.2.17",
|
|
76
79
|
"@storybook/web-components": "^10.2.17",
|
|
@@ -84,8 +87,5 @@
|
|
|
84
87
|
"lint-staged": "^15.4.3",
|
|
85
88
|
"sinon": "^19.0.0",
|
|
86
89
|
"storybook": "^10.0.0"
|
|
87
|
-
},
|
|
88
|
-
"overrides": {
|
|
89
|
-
"conventional-changelog-conventionalcommits": ">= 8.0.0"
|
|
90
90
|
}
|
|
91
91
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cz-toggle.d.ts","sourceRoot":"","sources":["../../src/controls/cz-toggle.ts"],"names":[],"mappings":""}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { css, sheet } from '@neovici/cosmoz-utils';
|
|
2
|
-
import { component, html, useCallback } from '@pionjs/pion';
|
|
3
|
-
import { live } from 'lit-html/directives/live.js';
|
|
4
|
-
import { when } from 'lit-html/directives/when.js';
|
|
5
|
-
import toggleStyles from '../styles/toggle';
|
|
6
|
-
const CzToggle = (host) => {
|
|
7
|
-
const { label, value, disabled, error } = host;
|
|
8
|
-
const onChange = useCallback((e) => host.dispatchEvent(new CustomEvent('change', {
|
|
9
|
-
detail: e.target.checked,
|
|
10
|
-
})), []);
|
|
11
|
-
return html `<input
|
|
12
|
-
id="toggle"
|
|
13
|
-
class="toggle"
|
|
14
|
-
part="toggle"
|
|
15
|
-
type="checkbox"
|
|
16
|
-
.checked=${live(!!value)}
|
|
17
|
-
?disabled=${disabled}
|
|
18
|
-
@change=${onChange}
|
|
19
|
-
/>
|
|
20
|
-
${when(label, () => html `<label for="toggle">${label}</label>`)}
|
|
21
|
-
<slot name="suffix"></slot>
|
|
22
|
-
${when(error, (error) => html `<div class="failure">${error}</div>`)} `;
|
|
23
|
-
};
|
|
24
|
-
const style = css `
|
|
25
|
-
${toggleStyles}
|
|
26
|
-
|
|
27
|
-
:host {
|
|
28
|
-
display: block;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
:host > * {
|
|
32
|
-
vertical-align: middle;
|
|
33
|
-
line-height: 0px;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
::slotted(*) {
|
|
37
|
-
margin-left: 5px;
|
|
38
|
-
}
|
|
39
|
-
`;
|
|
40
|
-
customElements.define('cz-toggle', component(CzToggle, { styleSheets: [sheet(style)] }));
|
package/dist/styles/toggle.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"toggle.d.ts","sourceRoot":"","sources":["../../src/styles/toggle.ts"],"names":[],"mappings":";AAEA,wBA4CE"}
|
package/dist/styles/toggle.js
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { tagged as css } from '@neovici/cosmoz-utils';
|
|
2
|
-
export default css `
|
|
3
|
-
.toggle {
|
|
4
|
-
appearance: none;
|
|
5
|
-
width: 35px;
|
|
6
|
-
height: 18px;
|
|
7
|
-
display: inline-block;
|
|
8
|
-
position: relative;
|
|
9
|
-
border-radius: 18px;
|
|
10
|
-
overflow: hidden;
|
|
11
|
-
outline: none;
|
|
12
|
-
border: none;
|
|
13
|
-
cursor: pointer;
|
|
14
|
-
background: var(--cz-toggle-color, #101010);
|
|
15
|
-
transition: background-color ease 0.25s;
|
|
16
|
-
margin: 0;
|
|
17
|
-
}
|
|
18
|
-
.toggle::before {
|
|
19
|
-
content: '';
|
|
20
|
-
display: block;
|
|
21
|
-
position: absolute;
|
|
22
|
-
z-index: 2;
|
|
23
|
-
width: 14px;
|
|
24
|
-
height: 14px;
|
|
25
|
-
background: var(--cz-toggle-thumb-color, #15b0d3);
|
|
26
|
-
left: 2px;
|
|
27
|
-
top: 2px;
|
|
28
|
-
border-radius: 50%;
|
|
29
|
-
transition: all cubic-bezier(0.3, 1.5, 0.7, 1) 0.25s;
|
|
30
|
-
}
|
|
31
|
-
.toggle:checked {
|
|
32
|
-
background: var(--cz-toggle-checked-color, #66d7f0);
|
|
33
|
-
}
|
|
34
|
-
.toggle:checked::before {
|
|
35
|
-
left: 19px;
|
|
36
|
-
}
|
|
37
|
-
.toggle + label {
|
|
38
|
-
padding-left: 16px;
|
|
39
|
-
font-size: 14px;
|
|
40
|
-
line-height: 18px;
|
|
41
|
-
cursor: pointer;
|
|
42
|
-
}
|
|
43
|
-
.toggle[disabled] {
|
|
44
|
-
opacity: 0.6;
|
|
45
|
-
}
|
|
46
|
-
`;
|