@vielzeug/craftit 2.1.0 → 3.0.1
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/README.md +58 -124
- package/dist/controls/a11y-control.cjs +1 -1
- package/dist/controls/a11y-control.cjs.map +1 -1
- package/dist/controls/a11y-control.d.ts +1 -1
- package/dist/controls/a11y-control.d.ts.map +1 -1
- package/dist/controls/a11y-control.js +1 -1
- package/dist/controls/a11y-control.js.map +1 -1
- package/dist/controls/checkable-control.cjs +1 -1
- package/dist/controls/checkable-control.cjs.map +1 -1
- package/dist/controls/checkable-control.d.ts +7 -7
- package/dist/controls/checkable-control.d.ts.map +1 -1
- package/dist/controls/checkable-control.js +1 -1
- package/dist/controls/checkable-control.js.map +1 -1
- package/dist/controls/choice-field-control.cjs +2 -0
- package/dist/controls/choice-field-control.cjs.map +1 -0
- package/dist/controls/choice-field-control.d.ts +3 -0
- package/dist/controls/choice-field-control.d.ts.map +1 -0
- package/dist/controls/choice-field-control.js +2 -0
- package/dist/controls/choice-field-control.js.map +1 -0
- package/dist/controls/field-control.cjs +1 -1
- package/dist/controls/field-control.cjs.map +1 -1
- package/dist/controls/field-control.d.ts +28 -73
- package/dist/controls/field-control.d.ts.map +1 -1
- package/dist/controls/field-control.js +1 -1
- package/dist/controls/field-control.js.map +1 -1
- package/dist/controls/index.d.ts +11 -9
- package/dist/controls/index.d.ts.map +1 -1
- package/dist/controls/internal/control-state.cjs +1 -1
- package/dist/controls/internal/control-state.cjs.map +1 -1
- package/dist/controls/internal/control-state.d.ts +6 -4
- package/dist/controls/internal/control-state.d.ts.map +1 -1
- package/dist/controls/internal/control-state.js +1 -1
- package/dist/controls/internal/control-state.js.map +1 -1
- package/dist/controls/internal/keyboard-utils.cjs.map +1 -1
- package/dist/controls/internal/keyboard-utils.js.map +1 -1
- package/dist/controls/internal/number-utils.cjs.map +1 -1
- package/dist/controls/internal/number-utils.js.map +1 -1
- package/dist/controls/internal/validation-utils.cjs.map +1 -1
- package/dist/controls/internal/validation-utils.js.map +1 -1
- package/dist/controls/list-control.cjs +1 -1
- package/dist/controls/list-control.cjs.map +1 -1
- package/dist/controls/list-control.d.ts +10 -8
- package/dist/controls/list-control.d.ts.map +1 -1
- package/dist/controls/list-control.js +1 -1
- package/dist/controls/list-control.js.map +1 -1
- package/dist/controls/overlay-control.cjs +1 -1
- package/dist/controls/overlay-control.cjs.map +1 -1
- package/dist/controls/overlay-control.d.ts +17 -14
- package/dist/controls/overlay-control.d.ts.map +1 -1
- package/dist/controls/overlay-control.js +1 -1
- package/dist/controls/overlay-control.js.map +1 -1
- package/dist/controls/popup-list-control.cjs +2 -0
- package/dist/controls/popup-list-control.cjs.map +1 -0
- package/dist/controls/popup-list-control.d.ts +160 -0
- package/dist/controls/popup-list-control.d.ts.map +1 -0
- package/dist/controls/popup-list-control.js +2 -0
- package/dist/controls/popup-list-control.js.map +1 -0
- package/dist/controls/press-control.cjs.map +1 -1
- package/dist/controls/press-control.js.map +1 -1
- package/dist/controls/slider-control.cjs.map +1 -1
- package/dist/controls/slider-control.js.map +1 -1
- package/dist/controls/spinner-control.cjs.map +1 -1
- package/dist/controls/spinner-control.js.map +1 -1
- package/dist/controls/swipe-control.cjs +2 -0
- package/dist/controls/swipe-control.cjs.map +1 -0
- package/dist/controls/swipe-control.d.ts +32 -0
- package/dist/controls/swipe-control.d.ts.map +1 -0
- package/dist/controls/swipe-control.js +2 -0
- package/dist/controls/swipe-control.js.map +1 -0
- package/dist/controls/text-field-control.cjs +2 -0
- package/dist/controls/text-field-control.cjs.map +1 -0
- package/dist/controls/text-field-control.d.ts +3 -0
- package/dist/controls/text-field-control.d.ts.map +1 -0
- package/dist/controls/text-field-control.js +2 -0
- package/dist/controls/text-field-control.js.map +1 -0
- package/dist/controls.cjs +1 -1
- package/dist/controls.js +1 -1
- package/dist/craftit.cjs +1 -1
- package/dist/craftit.cjs.map +1 -1
- package/dist/craftit.js +1 -1
- package/dist/craftit.js.map +1 -1
- package/dist/directives/classMap.cjs +2 -0
- package/dist/directives/classMap.cjs.map +1 -0
- package/dist/directives/classMap.d.ts +19 -0
- package/dist/directives/classMap.d.ts.map +1 -0
- package/dist/directives/classMap.js +2 -0
- package/dist/directives/classMap.js.map +1 -0
- package/dist/directives/each.cjs +1 -1
- package/dist/directives/each.cjs.map +1 -1
- package/dist/directives/each.d.ts +5 -30
- package/dist/directives/each.d.ts.map +1 -1
- package/dist/directives/each.js +1 -1
- package/dist/directives/each.js.map +1 -1
- package/dist/directives/guard.cjs +2 -0
- package/dist/directives/guard.cjs.map +1 -0
- package/dist/directives/guard.d.ts +10 -0
- package/dist/directives/guard.d.ts.map +1 -0
- package/dist/directives/guard.js +2 -0
- package/dist/directives/guard.js.map +1 -0
- package/dist/directives/live.cjs +2 -0
- package/dist/directives/live.cjs.map +1 -0
- package/dist/directives/live.d.ts +23 -0
- package/dist/directives/live.d.ts.map +1 -0
- package/dist/directives/live.js +2 -0
- package/dist/directives/live.js.map +1 -0
- package/dist/directives/raw.cjs +1 -1
- package/dist/directives/raw.cjs.map +1 -1
- package/dist/directives/raw.d.ts +3 -5
- package/dist/directives/raw.d.ts.map +1 -1
- package/dist/directives/raw.js +1 -1
- package/dist/directives/raw.js.map +1 -1
- package/dist/directives/resource.cjs +2 -0
- package/dist/directives/resource.cjs.map +1 -0
- package/dist/directives/resource.d.ts +32 -0
- package/dist/directives/resource.d.ts.map +1 -0
- package/dist/directives/resource.js +2 -0
- package/dist/directives/resource.js.map +1 -0
- package/dist/directives/styleMap.cjs +2 -0
- package/dist/directives/styleMap.cjs.map +1 -0
- package/dist/directives/styleMap.d.ts +11 -0
- package/dist/directives/styleMap.d.ts.map +1 -0
- package/dist/directives/styleMap.js +2 -0
- package/dist/directives/styleMap.js.map +1 -0
- package/dist/directives/when.cjs +1 -1
- package/dist/directives/when.cjs.map +1 -1
- package/dist/directives/when.d.ts +6 -19
- package/dist/directives/when.d.ts.map +1 -1
- package/dist/directives/when.js +1 -1
- package/dist/directives/when.js.map +1 -1
- package/dist/errors.cjs +2 -0
- package/dist/errors.cjs.map +1 -0
- package/dist/errors.d.ts +12 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +2 -0
- package/dist/errors.js.map +1 -0
- package/dist/form.cjs +1 -1
- package/dist/form.cjs.map +1 -1
- package/dist/form.d.ts +3 -17
- package/dist/form.d.ts.map +1 -1
- package/dist/form.js +1 -1
- package/dist/form.js.map +1 -1
- package/dist/host.cjs +1 -1
- package/dist/host.cjs.map +1 -1
- package/dist/host.d.ts +40 -37
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +1 -1
- package/dist/host.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +16 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/internal.cjs +1 -1
- package/dist/internal.cjs.map +1 -1
- package/dist/internal.d.ts +60 -120
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +1 -1
- package/dist/internal.js.map +1 -1
- package/dist/observers/index.d.ts +1 -0
- package/dist/observers/index.d.ts.map +1 -1
- package/dist/observers/intersection-observe.cjs +1 -1
- package/dist/observers/intersection-observe.cjs.map +1 -1
- package/dist/observers/intersection-observe.d.ts +1 -1
- package/dist/observers/intersection-observe.js +1 -1
- package/dist/observers/intersection-observe.js.map +1 -1
- package/dist/observers/media-observe.cjs +1 -1
- package/dist/observers/media-observe.cjs.map +1 -1
- package/dist/observers/media-observe.d.ts +1 -1
- package/dist/observers/media-observe.js +1 -1
- package/dist/observers/media-observe.js.map +1 -1
- package/dist/observers/mutation-observe.cjs +2 -0
- package/dist/observers/mutation-observe.cjs.map +1 -0
- package/dist/observers/mutation-observe.d.ts +10 -0
- package/dist/observers/mutation-observe.d.ts.map +1 -0
- package/dist/observers/mutation-observe.js +2 -0
- package/dist/observers/mutation-observe.js.map +1 -0
- package/dist/observers/resize-observe.cjs +1 -1
- package/dist/observers/resize-observe.cjs.map +1 -1
- package/dist/observers/resize-observe.d.ts +1 -1
- package/dist/observers/resize-observe.js +1 -1
- package/dist/observers/resize-observe.js.map +1 -1
- package/dist/observers.cjs +1 -1
- package/dist/observers.js +1 -1
- package/dist/props.cjs +1 -1
- package/dist/props.cjs.map +1 -1
- package/dist/props.d.ts +18 -31
- package/dist/props.d.ts.map +1 -1
- package/dist/props.js +1 -1
- package/dist/props.js.map +1 -1
- package/dist/registration.cjs +1 -1
- package/dist/registration.cjs.map +1 -1
- package/dist/registration.d.ts +27 -7
- package/dist/registration.d.ts.map +1 -1
- package/dist/registration.js +1 -1
- package/dist/registration.js.map +1 -1
- package/dist/runtime.cjs +1 -1
- package/dist/runtime.cjs.map +1 -1
- package/dist/runtime.d.ts +29 -17
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +1 -1
- package/dist/runtime.js.map +1 -1
- package/dist/template-bindings.cjs +1 -1
- package/dist/template-bindings.cjs.map +1 -1
- package/dist/template-bindings.d.ts +10 -47
- package/dist/template-bindings.d.ts.map +1 -1
- package/dist/template-bindings.js +1 -1
- package/dist/template-bindings.js.map +1 -1
- package/dist/template-compiler.cjs +1 -1
- package/dist/template-compiler.cjs.map +1 -1
- package/dist/template-compiler.d.ts +1 -21
- package/dist/template-compiler.d.ts.map +1 -1
- package/dist/template-compiler.js +1 -1
- package/dist/template-compiler.js.map +1 -1
- package/dist/testing/testing.cjs +1 -1
- package/dist/testing/testing.cjs.map +1 -1
- package/dist/testing/testing.d.ts +12 -5
- package/dist/testing/testing.d.ts.map +1 -1
- package/dist/testing/testing.js +1 -1
- package/dist/testing/testing.js.map +1 -1
- package/package.json +6 -12
- package/dist/component.cjs +0 -2
- package/dist/component.cjs.map +0 -1
- package/dist/component.d.ts +0 -39
- package/dist/component.d.ts.map +0 -1
- package/dist/component.js +0 -2
- package/dist/component.js.map +0 -1
- package/dist/controls/list-key-control.cjs +0 -2
- package/dist/controls/list-key-control.cjs.map +0 -1
- package/dist/controls/list-key-control.d.ts +0 -14
- package/dist/controls/list-key-control.d.ts.map +0 -1
- package/dist/controls/list-key-control.js +0 -2
- package/dist/controls/list-key-control.js.map +0 -1
- package/dist/directives/attr.cjs +0 -2
- package/dist/directives/attr.cjs.map +0 -1
- package/dist/directives/attr.d.ts +0 -12
- package/dist/directives/attr.d.ts.map +0 -1
- package/dist/directives/attr.js +0 -2
- package/dist/directives/attr.js.map +0 -1
- package/dist/directives/bind.cjs +0 -2
- package/dist/directives/bind.cjs.map +0 -1
- package/dist/directives/bind.d.ts +0 -38
- package/dist/directives/bind.d.ts.map +0 -1
- package/dist/directives/bind.js +0 -2
- package/dist/directives/bind.js.map +0 -1
- package/dist/directives/choose.cjs +0 -2
- package/dist/directives/choose.cjs.map +0 -1
- package/dist/directives/choose.d.ts +0 -39
- package/dist/directives/choose.d.ts.map +0 -1
- package/dist/directives/choose.js +0 -2
- package/dist/directives/choose.js.map +0 -1
- package/dist/directives/classes.cjs +0 -2
- package/dist/directives/classes.cjs.map +0 -1
- package/dist/directives/classes.d.ts +0 -20
- package/dist/directives/classes.d.ts.map +0 -1
- package/dist/directives/classes.js +0 -2
- package/dist/directives/classes.js.map +0 -1
- package/dist/directives/index.d.ts +0 -13
- package/dist/directives/index.d.ts.map +0 -1
- package/dist/directives/memo.cjs +0 -2
- package/dist/directives/memo.cjs.map +0 -1
- package/dist/directives/memo.d.ts +0 -27
- package/dist/directives/memo.d.ts.map +0 -1
- package/dist/directives/memo.js +0 -2
- package/dist/directives/memo.js.map +0 -1
- package/dist/directives/on.cjs +0 -2
- package/dist/directives/on.cjs.map +0 -1
- package/dist/directives/on.d.ts +0 -25
- package/dist/directives/on.d.ts.map +0 -1
- package/dist/directives/on.js +0 -2
- package/dist/directives/on.js.map +0 -1
- package/dist/directives/spread.cjs +0 -2
- package/dist/directives/spread.cjs.map +0 -1
- package/dist/directives/spread.d.ts +0 -14
- package/dist/directives/spread.d.ts.map +0 -1
- package/dist/directives/spread.js +0 -2
- package/dist/directives/spread.js.map +0 -1
- package/dist/directives/style.cjs +0 -2
- package/dist/directives/style.cjs.map +0 -1
- package/dist/directives/style.d.ts +0 -22
- package/dist/directives/style.d.ts.map +0 -1
- package/dist/directives/style.js +0 -2
- package/dist/directives/style.js.map +0 -1
- package/dist/directives/until.cjs +0 -2
- package/dist/directives/until.cjs.map +0 -1
- package/dist/directives/until.d.ts +0 -26
- package/dist/directives/until.d.ts.map +0 -1
- package/dist/directives/until.js +0 -2
- package/dist/directives/until.js.map +0 -1
- package/dist/directives.cjs +0 -1
- package/dist/directives.js +0 -1
- package/dist/runtime-bindings.cjs +0 -2
- package/dist/runtime-bindings.cjs.map +0 -1
- package/dist/runtime-bindings.d.ts +0 -6
- package/dist/runtime-bindings.d.ts.map +0 -1
- package/dist/runtime-bindings.js +0 -2
- package/dist/runtime-bindings.js.map +0 -1
- package/dist/runtime-core.cjs +0 -2
- package/dist/runtime-core.cjs.map +0 -1
- package/dist/runtime-core.d.ts +0 -21
- package/dist/runtime-core.d.ts.map +0 -1
- package/dist/runtime-core.js +0 -2
- package/dist/runtime-core.js.map +0 -1
- package/dist/runtime-lifecycle.cjs +0 -2
- package/dist/runtime-lifecycle.cjs.map +0 -1
- package/dist/runtime-lifecycle.d.ts +0 -24
- package/dist/runtime-lifecycle.d.ts.map +0 -1
- package/dist/runtime-lifecycle.js +0 -2
- package/dist/runtime-lifecycle.js.map +0 -1
- package/dist/template-dom.cjs +0 -2
- package/dist/template-dom.cjs.map +0 -1
- package/dist/template-dom.d.ts +0 -13
- package/dist/template-dom.d.ts.map +0 -1
- package/dist/template-dom.js +0 -2
- package/dist/template-dom.js.map +0 -1
- package/dist/template-html.cjs +0 -2
- package/dist/template-html.cjs.map +0 -1
- package/dist/template-html.d.ts +0 -23
- package/dist/template-html.d.ts.map +0 -1
- package/dist/template-html.js +0 -2
- package/dist/template-html.js.map +0 -1
- package/dist/template.cjs +0 -2
- package/dist/template.cjs.map +0 -1
- package/dist/template.d.ts +0 -10
- package/dist/template.d.ts.map +0 -1
- package/dist/template.js +0 -2
- package/dist/template.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# @vielzeug/craftit
|
|
2
2
|
|
|
3
|
-
> Functional web components with signals, typed props, and
|
|
3
|
+
> Functional web components with signals, typed props, lifecycle hooks, and headless controls.
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@vielzeug/craftit) [](https://opensource.org/licenses/MIT)
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Craftit is Vielzeug's custom-element authoring library built on `@vielzeug/stateit`.
|
|
8
8
|
|
|
9
9
|
## Installation
|
|
10
10
|
|
|
@@ -17,162 +17,96 @@ pnpm add @vielzeug/craftit
|
|
|
17
17
|
## Quick Start
|
|
18
18
|
|
|
19
19
|
```ts
|
|
20
|
-
import { computed, define, html, signal } from '@vielzeug/craftit';
|
|
20
|
+
import { computed, css, define, html, prop, signal } from '@vielzeug/craftit';
|
|
21
21
|
|
|
22
22
|
define('my-counter', {
|
|
23
|
-
|
|
23
|
+
props: {
|
|
24
|
+
label: prop.string('Count'),
|
|
25
|
+
step: prop.number(1),
|
|
26
|
+
},
|
|
27
|
+
setup(props, { host }) {
|
|
24
28
|
const count = signal(0);
|
|
25
29
|
const doubled = computed(() => count.value * 2);
|
|
26
30
|
|
|
27
|
-
|
|
28
|
-
|
|
31
|
+
host.class({ 'is-positive': () => count.value > 0 });
|
|
32
|
+
|
|
33
|
+
return () => html`
|
|
34
|
+
<button @click=${() => (count.value += props.step.value)}>
|
|
35
|
+
${props.label}: ${count}
|
|
36
|
+
</button>
|
|
29
37
|
<p>Doubled: ${doubled}</p>
|
|
30
38
|
`;
|
|
31
39
|
},
|
|
40
|
+
styles: [
|
|
41
|
+
css`
|
|
42
|
+
:host {
|
|
43
|
+
display: inline-grid;
|
|
44
|
+
gap: 0.5rem;
|
|
45
|
+
}
|
|
46
|
+
`,
|
|
47
|
+
],
|
|
32
48
|
});
|
|
33
49
|
```
|
|
34
50
|
|
|
35
|
-
##
|
|
36
|
-
|
|
37
|
-
- ✅ **Component authoring** — `define(tag, { props, setup, ... })`
|
|
38
|
-
- ✅ **Signals included** — all `@vielzeug/stateit` exports are re-exported
|
|
39
|
-
- ✅ **Reactive templates** — `html` tagged template with text/attr/prop/event/ref bindings
|
|
40
|
-
- ✅ **Lifecycle helpers** — `onMount`, `onCleanup`, `onError`, `handle`, `watch`, `effect`, `fire.*`
|
|
41
|
-
- ✅ **Typed component APIs** — `define`, `prop`, `typed`, setup-context `emit` and `slots`
|
|
42
|
-
- ✅ **Context / DI** — `createContext`, `provide`, `inject`, `syncContextProps`
|
|
43
|
-
- ✅ **Form-associated controls** — `defineField` with `ElementInternals`
|
|
44
|
-
- ✅ **Observer utilities (observers)** — `resizeObserver`, `intersectionObserver`, and `mediaObserver`
|
|
45
|
-
- ✅ **Directive subpath** — `@vielzeug/craftit/directives`
|
|
46
|
-
- ✅ **Test subpath** — `@vielzeug/craftit/testing`
|
|
47
|
-
|
|
48
|
-
## Entry Points
|
|
49
|
-
|
|
50
|
-
- `@vielzeug/craftit` — Main API with component authoring and stateit re-exports.
|
|
51
|
-
- `@vielzeug/craftit/controls` — Stable composables for controls and overlays.
|
|
52
|
-
- `@vielzeug/craftit/observers` — Stable browser observer composables.
|
|
53
|
-
- `@vielzeug/craftit/directives` — Directive helpers like `attrs`, `bind`, `choose`, `each`, `when`, and `until`.
|
|
54
|
-
- `@vielzeug/craftit/testing` — Mount, query, and event testing utilities.
|
|
55
|
-
|
|
56
|
-
## Usage Highlights
|
|
57
|
-
|
|
58
|
-
### Typed props + emits
|
|
59
|
-
|
|
60
|
-
```ts
|
|
61
|
-
import { define, html } from '@vielzeug/craftit';
|
|
51
|
+
## Authoring Model
|
|
62
52
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
},
|
|
68
|
-
setup({ emit, props }) {
|
|
69
|
-
return html`
|
|
70
|
-
<label>${props.label}</label>
|
|
71
|
-
<input :disabled=${props.disabled} @input=${(e: Event) => emit('change', (e.target as HTMLInputElement).value)} />
|
|
72
|
-
`;
|
|
73
|
-
},
|
|
74
|
-
});
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
### Directives subpath
|
|
53
|
+
- `setup(props, ctx)` returns a template function: `() => html\`...\``
|
|
54
|
+
- Use `onMounted()` for post-mount DOM initialization
|
|
55
|
+
- Use `onCleanup()` for teardown
|
|
56
|
+
- Use `onElement(ref, cb)` for ref-driven effects
|
|
78
57
|
|
|
79
58
|
```ts
|
|
80
|
-
import { define, html, signal } from '@vielzeug/craftit';
|
|
81
|
-
import { each, when } from '@vielzeug/craftit/directives';
|
|
59
|
+
import { define, html, onCleanup, onMounted, signal } from '@vielzeug/craftit';
|
|
82
60
|
|
|
83
|
-
define('
|
|
61
|
+
define('auto-save-field', {
|
|
84
62
|
setup() {
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
return html`
|
|
88
|
-
${when({
|
|
89
|
-
condition: () => todos.value.length > 0,
|
|
90
|
-
else: () => html`<p>No todos</p>`,
|
|
91
|
-
then: () =>
|
|
92
|
-
html`<ul>${each(todos, { key: (todo) => todo.id, render: (todo) => html`<li>${todo.text}</li>` })}</ul>`,
|
|
93
|
-
})}
|
|
94
|
-
`;
|
|
95
|
-
},
|
|
96
|
-
});
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
### Setup-context slots
|
|
100
|
-
|
|
101
|
-
```ts
|
|
102
|
-
import { define, effect, html } from '@vielzeug/craftit';
|
|
103
|
-
import { when } from '@vielzeug/craftit/directives';
|
|
63
|
+
const value = signal('');
|
|
104
64
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
effect(() => {
|
|
108
|
-
console.log('default elements:', slots.elements().value.length);
|
|
65
|
+
onMounted(() => {
|
|
66
|
+
console.log('ready for DOM interactions');
|
|
109
67
|
});
|
|
110
68
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
else: () => html`<h2>Fallback header</h2>`,
|
|
115
|
-
then: () => html`<slot name="header"></slot>`,
|
|
116
|
-
})}
|
|
117
|
-
${when({
|
|
118
|
-
condition: () => slots.has().value,
|
|
119
|
-
else: () => html`<p>No content yet</p>`,
|
|
120
|
-
then: () => html`<slot></slot>`,
|
|
121
|
-
})}
|
|
122
|
-
`;
|
|
123
|
-
},
|
|
124
|
-
});
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
Use `slots.has(name?)` for presence checks and `slots.elements(name?)` when you need flattened assigned elements.
|
|
128
|
-
|
|
129
|
-
### Form-associated field
|
|
130
|
-
|
|
131
|
-
```ts
|
|
132
|
-
import { define, defineField, html, signal } from '@vielzeug/craftit';
|
|
133
|
-
|
|
134
|
-
define('email-field', {
|
|
135
|
-
formAssociated: true,
|
|
136
|
-
setup() {
|
|
137
|
-
const value = signal('');
|
|
138
|
-
const field = defineField({ value });
|
|
69
|
+
onCleanup(() => {
|
|
70
|
+
console.log('saving', value.value);
|
|
71
|
+
});
|
|
139
72
|
|
|
140
|
-
return html`
|
|
141
|
-
<
|
|
142
|
-
type="email"
|
|
143
|
-
:value=${value}
|
|
73
|
+
return () => html`
|
|
74
|
+
<textarea
|
|
144
75
|
@input=${(e: Event) => {
|
|
145
|
-
value.value = (e.target as
|
|
146
|
-
field.setCustomValidity(value.value.includes('@') ? '' : 'Invalid email');
|
|
76
|
+
value.value = (e.target as HTMLTextAreaElement).value;
|
|
147
77
|
}}
|
|
148
|
-
|
|
78
|
+
></textarea>
|
|
149
79
|
`;
|
|
150
80
|
},
|
|
151
81
|
});
|
|
152
82
|
```
|
|
153
83
|
|
|
84
|
+
## Features
|
|
85
|
+
|
|
86
|
+
- Signals included: `signal`, `computed`, `watch`, `batch`, `untrack`, `scope`, and related primitives from `@vielzeug/stateit`
|
|
87
|
+
- Component authoring: `define(tag, { props, setup, styles, formAssociated })`
|
|
88
|
+
- Props: `prop.*` helpers and raw `PropDef` objects; shared bundles can type against `PropsDef<...>`
|
|
89
|
+
- Lifecycle hooks: `onMounted`, `onCleanup`, `onElement`, `effect`, `handle` (auto-cleans inside setup/scope; returns manual cleanup outside it)
|
|
90
|
+
- Directives: `each`, `classMap`, `styleMap`, `guard`, `when`, `live`, `until`, `raw`
|
|
91
|
+
- Host/slot APIs: `host.bind`, `syncAria`, `slots.has`, `slots.elements`
|
|
92
|
+
- Form-associated elements: `defineField()`
|
|
93
|
+
- Published subpaths: `@vielzeug/craftit/controls`, `@vielzeug/craftit/observers`, `@vielzeug/craftit/testing`
|
|
94
|
+
|
|
154
95
|
## API Summary
|
|
155
96
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
- Utilities: `html`, `css`, `createId`
|
|
165
|
-
- Re-exported from stateit: `signal`, `computed`, `batch`, `untrack`, `readonly`, and more
|
|
97
|
+
| Area | Exports |
|
|
98
|
+
| --- | --- |
|
|
99
|
+
| Component authoring | `define`, `prop`, `type ComponentDefinition`, `type SetupContextBag`, `type PropsDef`, `type PropDef` |
|
|
100
|
+
| Runtime | `onMounted`, `effect`, `handle`, `onCleanup`, `onElement` |
|
|
101
|
+
| Templates and directives | `html`, `css`, `each`, `classMap`, `styleMap`, `guard`, `when`, `live`, `until`, `raw` |
|
|
102
|
+
| Element references | `ref`, `refs`, `createId` |
|
|
103
|
+
| Context and slots | `createContext`, `provide`, `inject`, `injectStrict`, `syncAria` |
|
|
104
|
+
| Form | `defineField`, `type FormFieldOptions`, `type FormFieldHandle` |
|
|
166
105
|
|
|
167
106
|
## Documentation
|
|
168
107
|
|
|
169
108
|
Full docs at **[vielzeug.dev/craftit](https://vielzeug.dev/craftit)**
|
|
170
109
|
|
|
171
|
-
- [Overview](https://vielzeug.dev/craftit/) — Install and architecture overview
|
|
172
|
-
- [Usage Guide](https://vielzeug.dev/craftit/usage) — Practical patterns and subpath usage
|
|
173
|
-
- [API Reference](https://vielzeug.dev/craftit/api) — Complete signatures and types
|
|
174
|
-
- [Examples](https://vielzeug.dev/craftit/examples) — End-to-end component examples
|
|
175
|
-
|
|
176
110
|
## License
|
|
177
111
|
|
|
178
112
|
MIT © [Helmuth Saatkamp](https://github.com/helmuthdu) — Part of the [Vielzeug](https://github.com/helmuthdu/vielzeug) monorepo.
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require(`../runtime
|
|
1
|
+
const e=require(`../runtime.cjs`),t=require(`../internal.cjs`);var n=e=>{let t=e.querySelector(`slot`);return t instanceof HTMLSlotElement?t.assignedNodes({flatten:!0}).some(e=>(e.textContent?.trim().length??0)>0):(e.textContent?.trim().length??0)>0};function r(r){let i=e.currentElementOrThrow(),a=r.labelId||t.createId(`a11y-label`),o=r.helperId||t.createId(`a11y-helper`),s=(e,t,n)=>{e.getAttribute(t)!==n&&e.setAttribute(t,n)},c=(e,t)=>{e.textContent!==t&&(e.textContent=t)};s(i,`role`,r.role);let l=null,u=null,d=new Map,f=(e,t)=>{let n=new Set;for(let r of[e,t])if(r)for(let e of Array.from(r.querySelectorAll(`slot`)))e instanceof HTMLSlotElement&&n.add(e);for(let[e,t]of d)n.has(e)||(t(),d.delete(e));for(let e of n){if(d.has(e))continue;let t=()=>p();e.addEventListener(`slotchange`,t),d.set(e,()=>e.removeEventListener(`slotchange`,t))}},p=()=>{if(!i.shadowRoot)return;let e=l,t=u;f(e,t);let d=r.checked?.(),p=r.invalid?.(),m=r.helperText?.();e?(e.id!==a&&(e.id=a),n(e)?s(i,`aria-labelledby`,a):i.removeAttribute(`aria-labelledby`)):i.removeAttribute(`aria-labelledby`),t?(t.id!==o&&(t.id=o),m?(c(t,m),t.hidden&&=!1,s(i,`aria-describedby`,o),(r.helperTone?.()??`default`)===`error`?s(t,`role`,`alert`):t.removeAttribute(`role`)):(c(t,``),t.hidden||=!0,t.removeAttribute(`role`),i.removeAttribute(`aria-describedby`))):i.removeAttribute(`aria-describedby`),d===void 0?i.removeAttribute(`aria-checked`):s(i,`aria-checked`,d),p===void 0?i.removeAttribute(`aria-invalid`):s(i,`aria-invalid`,String(p))};return e.effect(()=>{p()}),e.onMounted(()=>{l=i.shadowRoot?.querySelector(`[data-a11y-label]`)??null,u=i.shadowRoot?.querySelector(`[data-a11y-helper]`)??null,p()}),e.onCleanup(()=>{for(let e of d.values())e();d.clear()}),{helperId:o,labelId:a}}exports.createA11yControl=r;
|
|
2
2
|
//# sourceMappingURL=a11y-control.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"a11y-control.cjs","names":[],"sources":["../../src/controls/a11y-control.ts"],"sourcesContent":["import { createId } from '../internal';\nimport { effect, onCleanup,
|
|
1
|
+
{"version":3,"file":"a11y-control.cjs","names":[],"sources":["../../src/controls/a11y-control.ts"],"sourcesContent":["import { createId } from '../internal';\nimport { currentElementOrThrow, effect, onCleanup, onMounted } from '../runtime';\n\nexport type A11yTone = 'default' | 'error';\n\nexport type A11yControlConfig = {\n checked?: () => 'true' | 'false' | 'mixed' | undefined;\n helperId?: string;\n helperText?: () => string | undefined;\n helperTone?: () => A11yTone;\n invalid?: () => boolean;\n labelId?: string;\n role: string;\n};\n\nexport type A11yControlHandle = {\n helperId: string;\n labelId: string;\n};\n\nconst hasLabelContent = (labelElement: HTMLElement): boolean => {\n const slot = labelElement.querySelector('slot');\n\n if (slot instanceof HTMLSlotElement) {\n return slot.assignedNodes({ flatten: true }).some((node) => (node.textContent?.trim().length ?? 0) > 0);\n }\n\n return (labelElement.textContent?.trim().length ?? 0) > 0;\n};\n\nexport function createA11yControl(config: A11yControlConfig): A11yControlHandle {\n const host = currentElementOrThrow();\n const labelId = config.labelId || createId('a11y-label');\n const helperId = config.helperId || createId('a11y-helper');\n\n const setAttr = (element: Element, name: string, value: string): void => {\n if (element.getAttribute(name) !== value) element.setAttribute(name, value);\n };\n\n const setText = (element: Node, value: string): void => {\n if (element.textContent !== value) element.textContent = value;\n };\n\n setAttr(host, 'role', config.role);\n\n let labelEl: HTMLElement | null = null;\n let helperEl: HTMLDivElement | null = null;\n\n const slotCleanupByElement = new Map<HTMLSlotElement, () => void>();\n\n const syncSlotListeners = (labelElement: HTMLElement | null, helperElement: HTMLDivElement | null): void => {\n const nextSlots = new Set<HTMLSlotElement>();\n\n for (const container of [labelElement, helperElement]) {\n if (!container) continue;\n\n for (const slot of Array.from(container.querySelectorAll('slot'))) {\n if (slot instanceof HTMLSlotElement) nextSlots.add(slot);\n }\n }\n\n for (const [slot, cleanup] of slotCleanupByElement) {\n if (nextSlots.has(slot)) continue;\n\n cleanup();\n slotCleanupByElement.delete(slot);\n }\n\n for (const slot of nextSlots) {\n if (slotCleanupByElement.has(slot)) continue;\n\n const slotHandler = () => sync();\n\n slot.addEventListener('slotchange', slotHandler);\n slotCleanupByElement.set(slot, () => slot.removeEventListener('slotchange', slotHandler));\n }\n };\n\n const sync = (): void => {\n const shadow = host.shadowRoot;\n\n if (!shadow) return;\n\n const labelElement = labelEl;\n const helperElement = helperEl;\n\n syncSlotListeners(labelElement, helperElement);\n\n const checked = config.checked?.();\n const invalid = config.invalid?.();\n const helperText = config.helperText?.();\n\n // Sync label\n if (labelElement) {\n if (labelElement.id !== labelId) labelElement.id = labelId;\n\n if (hasLabelContent(labelElement)) setAttr(host, 'aria-labelledby', labelId);\n else host.removeAttribute('aria-labelledby');\n } else {\n host.removeAttribute('aria-labelledby');\n }\n\n // Sync helper\n if (helperElement) {\n if (helperElement.id !== helperId) helperElement.id = helperId;\n\n if (helperText) {\n setText(helperElement, helperText);\n\n if (helperElement.hidden) helperElement.hidden = false;\n\n setAttr(host, 'aria-describedby', helperId);\n\n if ((config.helperTone?.() ?? 'default') === 'error') setAttr(helperElement, 'role', 'alert');\n else helperElement.removeAttribute('role');\n } else {\n setText(helperElement, '');\n\n if (!helperElement.hidden) helperElement.hidden = true;\n\n helperElement.removeAttribute('role');\n host.removeAttribute('aria-describedby');\n }\n } else {\n host.removeAttribute('aria-describedby');\n }\n\n // Sync checked\n if (checked === undefined) host.removeAttribute('aria-checked');\n else setAttr(host, 'aria-checked', checked);\n\n // Sync invalid\n if (invalid === undefined) host.removeAttribute('aria-invalid');\n else setAttr(host, 'aria-invalid', String(invalid));\n };\n\n // Keep ARIA in sync with reactive config changes.\n effect(() => {\n sync();\n });\n\n // Query shadow DOM refs once after first render, then sync.\n onMounted(() => {\n labelEl = (host.shadowRoot?.querySelector('[data-a11y-label]') ?? null) as HTMLElement | null;\n helperEl = (host.shadowRoot?.querySelector('[data-a11y-helper]') ?? null) as HTMLDivElement | null;\n sync();\n });\n\n onCleanup(() => {\n for (const cleanup of slotCleanupByElement.values()) cleanup();\n slotCleanupByElement.clear();\n });\n\n return { helperId, labelId };\n}\n"],"mappings":"+DAoBA,IAAM,EAAmB,GAAuC,CAC9D,IAAM,EAAO,EAAa,cAAc,MAAM,EAM9C,OAJI,aAAgB,gBACX,EAAK,cAAc,CAAE,QAAS,EAAK,CAAC,EAAE,KAAM,IAAU,EAAK,aAAa,KAAK,EAAE,QAAU,GAAK,CAAC,GAGhG,EAAa,aAAa,KAAK,EAAE,QAAU,GAAK,CAC1D,EAEA,SAAgB,EAAkB,EAA8C,CAC9E,IAAM,EAAO,EAAA,sBAAsB,EAC7B,EAAU,EAAO,SAAW,EAAA,SAAS,YAAY,EACjD,EAAW,EAAO,UAAY,EAAA,SAAS,aAAa,EAEpD,GAAW,EAAkB,EAAc,IAAwB,CACnE,EAAQ,aAAa,CAAI,IAAM,GAAO,EAAQ,aAAa,EAAM,CAAK,CAC5E,EAEM,GAAW,EAAe,IAAwB,CAClD,EAAQ,cAAgB,IAAO,EAAQ,YAAc,EAC3D,EAEA,EAAQ,EAAM,OAAQ,EAAO,IAAI,EAEjC,IAAI,EAA8B,KAC9B,EAAkC,KAEhC,EAAuB,IAAI,IAE3B,GAAqB,EAAkC,IAA+C,CAC1G,IAAM,EAAY,IAAI,IAEtB,IAAK,IAAM,IAAa,CAAC,EAAc,CAAa,EAC7C,KAEL,IAAK,IAAM,KAAQ,MAAM,KAAK,EAAU,iBAAiB,MAAM,CAAC,EAC1D,aAAgB,iBAAiB,EAAU,IAAI,CAAI,EAI3D,IAAK,GAAM,CAAC,EAAM,KAAY,EACxB,EAAU,IAAI,CAAI,IAEtB,EAAQ,EACR,EAAqB,OAAO,CAAI,GAGlC,IAAK,IAAM,KAAQ,EAAW,CAC5B,GAAI,EAAqB,IAAI,CAAI,EAAG,SAEpC,IAAM,MAAoB,EAAK,EAE/B,EAAK,iBAAiB,aAAc,CAAW,EAC/C,EAAqB,IAAI,MAAY,EAAK,oBAAoB,aAAc,CAAW,CAAC,CAC1F,CACF,EAEM,MAAmB,CAGvB,GAAI,CAFW,EAAK,WAEP,OAEb,IAAM,EAAe,EACf,EAAgB,EAEtB,EAAkB,EAAc,CAAa,EAE7C,IAAM,EAAU,EAAO,UAAU,EAC3B,EAAU,EAAO,UAAU,EAC3B,EAAa,EAAO,aAAa,EAGnC,GACE,EAAa,KAAO,IAAS,EAAa,GAAK,GAE/C,EAAgB,CAAY,EAAG,EAAQ,EAAM,kBAAmB,CAAO,EACtE,EAAK,gBAAgB,iBAAiB,GAE3C,EAAK,gBAAgB,iBAAiB,EAIpC,GACE,EAAc,KAAO,IAAU,EAAc,GAAK,GAElD,GACF,EAAQ,EAAe,CAAU,EAEjC,AAA0B,EAAc,SAAS,GAEjD,EAAQ,EAAM,mBAAoB,CAAQ,GAErC,EAAO,aAAa,GAAK,aAAe,QAAS,EAAQ,EAAe,OAAQ,OAAO,EACvF,EAAc,gBAAgB,MAAM,IAEzC,EAAQ,EAAe,EAAE,EAEzB,AAA2B,EAAc,SAAS,GAElD,EAAc,gBAAgB,MAAM,EACpC,EAAK,gBAAgB,kBAAkB,IAGzC,EAAK,gBAAgB,kBAAkB,EAIrC,IAAY,IAAA,GAAW,EAAK,gBAAgB,cAAc,EACzD,EAAQ,EAAM,eAAgB,CAAO,EAGtC,IAAY,IAAA,GAAW,EAAK,gBAAgB,cAAc,EACzD,EAAQ,EAAM,eAAgB,OAAO,CAAO,CAAC,CACpD,EAmBA,OAhBA,EAAA,WAAa,CACX,EAAK,CACP,CAAC,EAGD,EAAA,cAAgB,CACd,EAAW,EAAK,YAAY,cAAc,mBAAmB,GAAK,KAClE,EAAY,EAAK,YAAY,cAAc,oBAAoB,GAAK,KACpE,EAAK,CACP,CAAC,EAED,EAAA,cAAgB,CACd,IAAK,IAAM,KAAW,EAAqB,OAAO,EAAG,EAAQ,EAC7D,EAAqB,MAAM,CAC7B,CAAC,EAEM,CAAE,WAAU,SAAQ,CAC7B"}
|
|
@@ -12,5 +12,5 @@ export type A11yControlHandle = {
|
|
|
12
12
|
helperId: string;
|
|
13
13
|
labelId: string;
|
|
14
14
|
};
|
|
15
|
-
export declare function createA11yControl(
|
|
15
|
+
export declare function createA11yControl(config: A11yControlConfig): A11yControlHandle;
|
|
16
16
|
//# sourceMappingURL=a11y-control.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"a11y-control.d.ts","sourceRoot":"","sources":["../../src/controls/a11y-control.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAC;AAE3C,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,CAAC,EAAE,MAAM,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,SAAS,CAAC;IACvD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,MAAM,GAAG,SAAS,CAAC;IACtC,UAAU,CAAC,EAAE,MAAM,QAAQ,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,OAAO,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAYF,wBAAgB,iBAAiB,CAAC,
|
|
1
|
+
{"version":3,"file":"a11y-control.d.ts","sourceRoot":"","sources":["../../src/controls/a11y-control.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAC;AAE3C,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,CAAC,EAAE,MAAM,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,SAAS,CAAC;IACvD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,MAAM,GAAG,SAAS,CAAC;IACtC,UAAU,CAAC,EAAE,MAAM,QAAQ,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,OAAO,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAYF,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,iBAAiB,GAAG,iBAAiB,CA4H9E"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{currentElementOrThrow as e,effect as t,onCleanup as n,onMounted as r}from"../runtime.js";import{createId as i}from"../internal.js";var a=e=>{let t=e.querySelector(`slot`);return t instanceof HTMLSlotElement?t.assignedNodes({flatten:!0}).some(e=>(e.textContent?.trim().length??0)>0):(e.textContent?.trim().length??0)>0};function o(o){let s=e(),c=o.labelId||i(`a11y-label`),l=o.helperId||i(`a11y-helper`),u=(e,t,n)=>{e.getAttribute(t)!==n&&e.setAttribute(t,n)},d=(e,t)=>{e.textContent!==t&&(e.textContent=t)};u(s,`role`,o.role);let f=null,p=null,m=new Map,h=(e,t)=>{let n=new Set;for(let r of[e,t])if(r)for(let e of Array.from(r.querySelectorAll(`slot`)))e instanceof HTMLSlotElement&&n.add(e);for(let[e,t]of m)n.has(e)||(t(),m.delete(e));for(let e of n){if(m.has(e))continue;let t=()=>g();e.addEventListener(`slotchange`,t),m.set(e,()=>e.removeEventListener(`slotchange`,t))}},g=()=>{if(!s.shadowRoot)return;let e=f,t=p;h(e,t);let n=o.checked?.(),r=o.invalid?.(),i=o.helperText?.();e?(e.id!==c&&(e.id=c),a(e)?u(s,`aria-labelledby`,c):s.removeAttribute(`aria-labelledby`)):s.removeAttribute(`aria-labelledby`),t?(t.id!==l&&(t.id=l),i?(d(t,i),t.hidden&&=!1,u(s,`aria-describedby`,l),(o.helperTone?.()??`default`)===`error`?u(t,`role`,`alert`):t.removeAttribute(`role`)):(d(t,``),t.hidden||=!0,t.removeAttribute(`role`),s.removeAttribute(`aria-describedby`))):s.removeAttribute(`aria-describedby`),n===void 0?s.removeAttribute(`aria-checked`):u(s,`aria-checked`,n),r===void 0?s.removeAttribute(`aria-invalid`):u(s,`aria-invalid`,String(r))};return t(()=>{g()}),r(()=>{f=s.shadowRoot?.querySelector(`[data-a11y-label]`)??null,p=s.shadowRoot?.querySelector(`[data-a11y-helper]`)??null,g()}),n(()=>{for(let e of m.values())e();m.clear()}),{helperId:l,labelId:c}}export{o as createA11yControl};
|
|
2
2
|
//# sourceMappingURL=a11y-control.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"a11y-control.js","names":[],"sources":["../../src/controls/a11y-control.ts"],"sourcesContent":["import { createId } from '../internal';\nimport { effect, onCleanup,
|
|
1
|
+
{"version":3,"file":"a11y-control.js","names":[],"sources":["../../src/controls/a11y-control.ts"],"sourcesContent":["import { createId } from '../internal';\nimport { currentElementOrThrow, effect, onCleanup, onMounted } from '../runtime';\n\nexport type A11yTone = 'default' | 'error';\n\nexport type A11yControlConfig = {\n checked?: () => 'true' | 'false' | 'mixed' | undefined;\n helperId?: string;\n helperText?: () => string | undefined;\n helperTone?: () => A11yTone;\n invalid?: () => boolean;\n labelId?: string;\n role: string;\n};\n\nexport type A11yControlHandle = {\n helperId: string;\n labelId: string;\n};\n\nconst hasLabelContent = (labelElement: HTMLElement): boolean => {\n const slot = labelElement.querySelector('slot');\n\n if (slot instanceof HTMLSlotElement) {\n return slot.assignedNodes({ flatten: true }).some((node) => (node.textContent?.trim().length ?? 0) > 0);\n }\n\n return (labelElement.textContent?.trim().length ?? 0) > 0;\n};\n\nexport function createA11yControl(config: A11yControlConfig): A11yControlHandle {\n const host = currentElementOrThrow();\n const labelId = config.labelId || createId('a11y-label');\n const helperId = config.helperId || createId('a11y-helper');\n\n const setAttr = (element: Element, name: string, value: string): void => {\n if (element.getAttribute(name) !== value) element.setAttribute(name, value);\n };\n\n const setText = (element: Node, value: string): void => {\n if (element.textContent !== value) element.textContent = value;\n };\n\n setAttr(host, 'role', config.role);\n\n let labelEl: HTMLElement | null = null;\n let helperEl: HTMLDivElement | null = null;\n\n const slotCleanupByElement = new Map<HTMLSlotElement, () => void>();\n\n const syncSlotListeners = (labelElement: HTMLElement | null, helperElement: HTMLDivElement | null): void => {\n const nextSlots = new Set<HTMLSlotElement>();\n\n for (const container of [labelElement, helperElement]) {\n if (!container) continue;\n\n for (const slot of Array.from(container.querySelectorAll('slot'))) {\n if (slot instanceof HTMLSlotElement) nextSlots.add(slot);\n }\n }\n\n for (const [slot, cleanup] of slotCleanupByElement) {\n if (nextSlots.has(slot)) continue;\n\n cleanup();\n slotCleanupByElement.delete(slot);\n }\n\n for (const slot of nextSlots) {\n if (slotCleanupByElement.has(slot)) continue;\n\n const slotHandler = () => sync();\n\n slot.addEventListener('slotchange', slotHandler);\n slotCleanupByElement.set(slot, () => slot.removeEventListener('slotchange', slotHandler));\n }\n };\n\n const sync = (): void => {\n const shadow = host.shadowRoot;\n\n if (!shadow) return;\n\n const labelElement = labelEl;\n const helperElement = helperEl;\n\n syncSlotListeners(labelElement, helperElement);\n\n const checked = config.checked?.();\n const invalid = config.invalid?.();\n const helperText = config.helperText?.();\n\n // Sync label\n if (labelElement) {\n if (labelElement.id !== labelId) labelElement.id = labelId;\n\n if (hasLabelContent(labelElement)) setAttr(host, 'aria-labelledby', labelId);\n else host.removeAttribute('aria-labelledby');\n } else {\n host.removeAttribute('aria-labelledby');\n }\n\n // Sync helper\n if (helperElement) {\n if (helperElement.id !== helperId) helperElement.id = helperId;\n\n if (helperText) {\n setText(helperElement, helperText);\n\n if (helperElement.hidden) helperElement.hidden = false;\n\n setAttr(host, 'aria-describedby', helperId);\n\n if ((config.helperTone?.() ?? 'default') === 'error') setAttr(helperElement, 'role', 'alert');\n else helperElement.removeAttribute('role');\n } else {\n setText(helperElement, '');\n\n if (!helperElement.hidden) helperElement.hidden = true;\n\n helperElement.removeAttribute('role');\n host.removeAttribute('aria-describedby');\n }\n } else {\n host.removeAttribute('aria-describedby');\n }\n\n // Sync checked\n if (checked === undefined) host.removeAttribute('aria-checked');\n else setAttr(host, 'aria-checked', checked);\n\n // Sync invalid\n if (invalid === undefined) host.removeAttribute('aria-invalid');\n else setAttr(host, 'aria-invalid', String(invalid));\n };\n\n // Keep ARIA in sync with reactive config changes.\n effect(() => {\n sync();\n });\n\n // Query shadow DOM refs once after first render, then sync.\n onMounted(() => {\n labelEl = (host.shadowRoot?.querySelector('[data-a11y-label]') ?? null) as HTMLElement | null;\n helperEl = (host.shadowRoot?.querySelector('[data-a11y-helper]') ?? null) as HTMLDivElement | null;\n sync();\n });\n\n onCleanup(() => {\n for (const cleanup of slotCleanupByElement.values()) cleanup();\n slotCleanupByElement.clear();\n });\n\n return { helperId, labelId };\n}\n"],"mappings":"0IAoBA,IAAM,EAAmB,GAAuC,CAC9D,IAAM,EAAO,EAAa,cAAc,MAAM,EAM9C,OAJI,aAAgB,gBACX,EAAK,cAAc,CAAE,QAAS,EAAK,CAAC,EAAE,KAAM,IAAU,EAAK,aAAa,KAAK,EAAE,QAAU,GAAK,CAAC,GAGhG,EAAa,aAAa,KAAK,EAAE,QAAU,GAAK,CAC1D,EAEA,SAAgB,EAAkB,EAA8C,CAC9E,IAAM,EAAO,EAAsB,EAC7B,EAAU,EAAO,SAAW,EAAS,YAAY,EACjD,EAAW,EAAO,UAAY,EAAS,aAAa,EAEpD,GAAW,EAAkB,EAAc,IAAwB,CACnE,EAAQ,aAAa,CAAI,IAAM,GAAO,EAAQ,aAAa,EAAM,CAAK,CAC5E,EAEM,GAAW,EAAe,IAAwB,CAClD,EAAQ,cAAgB,IAAO,EAAQ,YAAc,EAC3D,EAEA,EAAQ,EAAM,OAAQ,EAAO,IAAI,EAEjC,IAAI,EAA8B,KAC9B,EAAkC,KAEhC,EAAuB,IAAI,IAE3B,GAAqB,EAAkC,IAA+C,CAC1G,IAAM,EAAY,IAAI,IAEtB,IAAK,IAAM,IAAa,CAAC,EAAc,CAAa,EAC7C,KAEL,IAAK,IAAM,KAAQ,MAAM,KAAK,EAAU,iBAAiB,MAAM,CAAC,EAC1D,aAAgB,iBAAiB,EAAU,IAAI,CAAI,EAI3D,IAAK,GAAM,CAAC,EAAM,KAAY,EACxB,EAAU,IAAI,CAAI,IAEtB,EAAQ,EACR,EAAqB,OAAO,CAAI,GAGlC,IAAK,IAAM,KAAQ,EAAW,CAC5B,GAAI,EAAqB,IAAI,CAAI,EAAG,SAEpC,IAAM,MAAoB,EAAK,EAE/B,EAAK,iBAAiB,aAAc,CAAW,EAC/C,EAAqB,IAAI,MAAY,EAAK,oBAAoB,aAAc,CAAW,CAAC,CAC1F,CACF,EAEM,MAAmB,CAGvB,GAAI,CAFW,EAAK,WAEP,OAEb,IAAM,EAAe,EACf,EAAgB,EAEtB,EAAkB,EAAc,CAAa,EAE7C,IAAM,EAAU,EAAO,UAAU,EAC3B,EAAU,EAAO,UAAU,EAC3B,EAAa,EAAO,aAAa,EAGnC,GACE,EAAa,KAAO,IAAS,EAAa,GAAK,GAE/C,EAAgB,CAAY,EAAG,EAAQ,EAAM,kBAAmB,CAAO,EACtE,EAAK,gBAAgB,iBAAiB,GAE3C,EAAK,gBAAgB,iBAAiB,EAIpC,GACE,EAAc,KAAO,IAAU,EAAc,GAAK,GAElD,GACF,EAAQ,EAAe,CAAU,EAEjC,AAA0B,EAAc,SAAS,GAEjD,EAAQ,EAAM,mBAAoB,CAAQ,GAErC,EAAO,aAAa,GAAK,aAAe,QAAS,EAAQ,EAAe,OAAQ,OAAO,EACvF,EAAc,gBAAgB,MAAM,IAEzC,EAAQ,EAAe,EAAE,EAEzB,AAA2B,EAAc,SAAS,GAElD,EAAc,gBAAgB,MAAM,EACpC,EAAK,gBAAgB,kBAAkB,IAGzC,EAAK,gBAAgB,kBAAkB,EAIrC,IAAY,IAAA,GAAW,EAAK,gBAAgB,cAAc,EACzD,EAAQ,EAAM,eAAgB,CAAO,EAGtC,IAAY,IAAA,GAAW,EAAK,gBAAgB,cAAc,EACzD,EAAQ,EAAM,eAAgB,OAAO,CAAO,CAAC,CACpD,EAmBA,OAhBA,MAAa,CACX,EAAK,CACP,CAAC,EAGD,MAAgB,CACd,EAAW,EAAK,YAAY,cAAc,mBAAmB,GAAK,KAClE,EAAY,EAAK,YAAY,cAAc,oBAAoB,GAAK,KACpE,EAAK,CACP,CAAC,EAED,MAAgB,CACd,IAAK,IAAM,KAAW,EAAqB,OAAO,EAAG,EAAQ,EAC7D,EAAqB,MAAM,CAC7B,CAAC,EAEM,CAAE,WAAU,SAAQ,CAC7B"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require(`./a11y-control.cjs`),t=require(`./field-control.cjs`),n=require(`./press-control.cjs`);
|
|
1
|
+
const e=require(`./a11y-control.cjs`),t=require(`./field-control.cjs`),n=require(`./press-control.cjs`);let r=require(`@vielzeug/stateit`);var i=e=>{let n=(0,r.signal)(``),i=(0,r.signal)(!!e.checked.value),a=(0,r.signal)(!!e.indeterminate?.value),o=t.createAssistiveState({error:e.error,helper:e.helper});(0,r.watch)(e.checked,e=>{i.value=!!e},{immediate:!0}),e.indeterminate&&(0,r.watch)(e.indeterminate,e=>{a.value=!!e},{immediate:!0});let{base:s,triggerValidation:c}=t.createFieldControlBase(e,{toFormValue:e=>e,value:(0,r.computed)(()=>a.value?null:i.value?e.value.value??``:null)});(0,r.watch)(e.value,e=>{n.value=String(e??``)},{immediate:!0});let l=t=>({checked:i.value,originalEvent:t,value:e.value.value??``}),u=t=>{if(!s.disabled.value){if(e.group){a.value=!1,e.group.toggle(e.value.value??``,t),e.onToggle?.(l(t));return}e.clearIndeterminateFirst&&a.value||(i.value=!i.value),a.value=!1,e.onToggle?.(l(t))}};return{...s,assistive:o,checked:i,indeterminate:a,toggle:u,triggerValidation:c,value:n}},a=t=>{let r=i(t),a=e.createA11yControl({checked:()=>t.role===`checkbox`&&r.indeterminate.value?`mixed`:r.checked.value?`true`:`false`,helperText:()=>r.assistive.value.errorText||r.assistive.value.helperText,helperTone:()=>r.assistive.value.errorText?`error`:`default`,invalid:()=>!!r.assistive.value.errorText,role:t.role}),o=n.createPressControl({disabled:()=>r.disabled.value,onPress:e=>{if(t.onPress){t.onPress(r,e);return}r.toggle(e)}});return{...r,handleClick:o.handleClick,handleKeydown:o.handleKeydown,helperId:a.helperId,labelId:a.labelId}};exports.createCheckableFieldControl=a;
|
|
2
2
|
//# sourceMappingURL=checkable-control.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checkable-control.cjs","names":[],"sources":["../../src/controls/checkable-control.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"checkable-control.cjs","names":[],"sources":["../../src/controls/checkable-control.ts"],"sourcesContent":["import { computed, signal, watch } from '@vielzeug/stateit';\n\nimport { createA11yControl } from './a11y-control';\nimport {\n createAssistiveState,\n createFieldControlBase,\n type CheckableChangePayload,\n type CheckableStateHandle,\n type CheckableStateOptions,\n} from './field-control';\nimport { createPressControl } from './press-control';\n\nexport type CheckableFieldControlOptions = CheckableStateOptions & {\n onPress?: (control: CheckableStateHandle, originalEvent: Event) => void;\n role: 'checkbox' | 'radio' | 'switch';\n};\n\nexport type CheckableFieldControlHandle = CheckableStateHandle & {\n handleClick: (event: MouseEvent) => boolean;\n handleKeydown: (event: KeyboardEvent) => boolean;\n helperId: string;\n labelId: string;\n};\n\n/** @internal */\nexport const createCheckableState = (options: CheckableStateOptions): CheckableStateHandle => {\n const value = signal('');\n const checked = signal(Boolean(options.checked.value));\n const indeterminate = signal(Boolean(options.indeterminate?.value));\n const assistive = createAssistiveState({ error: options.error, helper: options.helper });\n\n watch(\n options.checked,\n (next) => {\n checked.value = Boolean(next);\n },\n { immediate: true },\n );\n\n if (options.indeterminate) {\n watch(\n options.indeterminate,\n (next) => {\n indeterminate.value = Boolean(next);\n },\n { immediate: true },\n );\n }\n\n const { base, triggerValidation } = createFieldControlBase(options, {\n toFormValue: (nextValue: string | null) => nextValue,\n value: computed(() => {\n if (indeterminate.value) return null;\n\n return checked.value ? (options.value.value ?? '') : null;\n }),\n });\n\n watch(\n options.value,\n (next) => {\n value.value = String(next ?? '');\n },\n { immediate: true },\n );\n\n const createPayload = (event: Event): CheckableChangePayload => ({\n checked: checked.value,\n originalEvent: event,\n value: options.value.value ?? '',\n });\n\n const toggle = (event: Event): void => {\n if (base.disabled.value) return;\n\n if (options.group) {\n indeterminate.value = false;\n options.group.toggle(options.value.value ?? '', event);\n options.onToggle?.(createPayload(event));\n\n return;\n }\n\n if (options.clearIndeterminateFirst && indeterminate.value) {\n indeterminate.value = false;\n } else {\n checked.value = !checked.value;\n indeterminate.value = false;\n }\n\n options.onToggle?.(createPayload(event));\n };\n\n return {\n ...base,\n assistive,\n checked,\n indeterminate,\n toggle,\n triggerValidation,\n value,\n };\n};\n\nexport const createCheckableFieldControl = (options: CheckableFieldControlOptions): CheckableFieldControlHandle => {\n const control = createCheckableState(options);\n const a11y = createA11yControl({\n checked: () =>\n options.role === 'checkbox' && control.indeterminate.value ? 'mixed' : control.checked.value ? 'true' : 'false',\n helperText: () => control.assistive.value.errorText || control.assistive.value.helperText,\n helperTone: () => (control.assistive.value.errorText ? 'error' : 'default'),\n invalid: () => Boolean(control.assistive.value.errorText),\n role: options.role,\n });\n\n const press = createPressControl({\n disabled: () => control.disabled.value,\n onPress: (originalEvent) => {\n if (options.onPress) {\n options.onPress(control, originalEvent);\n\n return;\n }\n\n control.toggle(originalEvent);\n },\n });\n\n return {\n ...control,\n handleClick: press.handleClick,\n handleKeydown: press.handleKeydown,\n helperId: a11y.helperId,\n labelId: a11y.labelId,\n };\n};\n"],"mappings":"2IAyBA,IAAa,EAAwB,GAAyD,CAC5F,IAAM,GAAA,EAAA,EAAA,QAAe,EAAE,EACjB,GAAA,EAAA,EAAA,QAAiB,EAAQ,EAAQ,QAAQ,KAAM,EAC/C,GAAA,EAAA,EAAA,QAAuB,EAAQ,EAAQ,eAAe,KAAM,EAC5D,EAAY,EAAA,qBAAqB,CAAE,MAAO,EAAQ,MAAO,OAAQ,EAAQ,MAAO,CAAC,GAEvF,EAAA,EAAA,OACE,EAAQ,QACP,GAAS,CACR,EAAQ,MAAQ,EAAQ,CAC1B,EACA,CAAE,UAAW,EAAK,CACpB,EAEI,EAAQ,gBACV,EAAA,EAAA,OACE,EAAQ,cACP,GAAS,CACR,EAAc,MAAQ,EAAQ,CAChC,EACA,CAAE,UAAW,EAAK,CACpB,EAGF,GAAM,CAAE,OAAM,qBAAsB,EAAA,uBAAuB,EAAS,CAClE,YAAc,GAA6B,EAC3C,OAAA,EAAA,EAAA,cACM,EAAc,MAAc,KAEzB,EAAQ,MAAS,EAAQ,MAAM,OAAS,GAAM,IACtD,CACH,CAAC,GAED,EAAA,EAAA,OACE,EAAQ,MACP,GAAS,CACR,EAAM,MAAQ,OAAO,GAAQ,EAAE,CACjC,EACA,CAAE,UAAW,EAAK,CACpB,EAEA,IAAM,EAAiB,IAA0C,CAC/D,QAAS,EAAQ,MACjB,cAAe,EACf,MAAO,EAAQ,MAAM,OAAS,EAChC,GAEM,EAAU,GAAuB,CACjC,MAAK,SAAS,MAElB,IAAI,EAAQ,MAAO,CACjB,EAAc,MAAQ,GACtB,EAAQ,MAAM,OAAO,EAAQ,MAAM,OAAS,GAAI,CAAK,EACrD,EAAQ,WAAW,EAAc,CAAK,CAAC,EAEvC,MACF,CAEI,EAAQ,yBAA2B,EAAc,QAGnD,EAAQ,MAAQ,CAAC,EAAQ,OAFzB,EAAc,MAAQ,GAMxB,EAAQ,WAAW,EAAc,CAAK,CAAC,CATvC,CAUF,EAEA,MAAO,CACL,GAAG,EACH,YACA,UACA,gBACA,SACA,oBACA,OACF,CACF,EAEa,EAA+B,GAAuE,CACjH,IAAM,EAAU,EAAqB,CAAO,EACtC,EAAO,EAAA,kBAAkB,CAC7B,YACE,EAAQ,OAAS,YAAc,EAAQ,cAAc,MAAQ,QAAU,EAAQ,QAAQ,MAAQ,OAAS,QAC1G,eAAkB,EAAQ,UAAU,MAAM,WAAa,EAAQ,UAAU,MAAM,WAC/E,eAAmB,EAAQ,UAAU,MAAM,UAAY,QAAU,UACjE,YAAe,EAAQ,EAAQ,UAAU,MAAM,UAC/C,KAAM,EAAQ,IAChB,CAAC,EAEK,EAAQ,EAAA,mBAAmB,CAC/B,aAAgB,EAAQ,SAAS,MACjC,QAAU,GAAkB,CAC1B,GAAI,EAAQ,QAAS,CACnB,EAAQ,QAAQ,EAAS,CAAa,EAEtC,MACF,CAEA,EAAQ,OAAO,CAAa,CAC9B,CACF,CAAC,EAED,MAAO,CACL,GAAG,EACH,YAAa,EAAM,YACnB,cAAe,EAAM,cACrB,SAAU,EAAK,SACf,QAAS,EAAK,OAChB,CACF"}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { type A11yControlHandle } from './a11y-control';
|
|
2
1
|
import { type CheckableStateHandle, type CheckableStateOptions } from './field-control';
|
|
3
|
-
import { type PressControl } from './press-control';
|
|
4
2
|
export type CheckableFieldControlOptions = CheckableStateOptions & {
|
|
5
|
-
host: HTMLElement;
|
|
6
3
|
onPress?: (control: CheckableStateHandle, originalEvent: Event) => void;
|
|
7
4
|
role: 'checkbox' | 'radio' | 'switch';
|
|
8
5
|
};
|
|
9
|
-
export type CheckableFieldControlHandle = {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
6
|
+
export type CheckableFieldControlHandle = CheckableStateHandle & {
|
|
7
|
+
handleClick: (event: MouseEvent) => boolean;
|
|
8
|
+
handleKeydown: (event: KeyboardEvent) => boolean;
|
|
9
|
+
helperId: string;
|
|
10
|
+
labelId: string;
|
|
13
11
|
};
|
|
12
|
+
/** @internal */
|
|
13
|
+
export declare const createCheckableState: (options: CheckableStateOptions) => CheckableStateHandle;
|
|
14
14
|
export declare const createCheckableFieldControl: (options: CheckableFieldControlOptions) => CheckableFieldControlHandle;
|
|
15
15
|
//# sourceMappingURL=checkable-control.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checkable-control.d.ts","sourceRoot":"","sources":["../../src/controls/checkable-control.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"checkable-control.d.ts","sourceRoot":"","sources":["../../src/controls/checkable-control.ts"],"names":[],"mappings":"AAGA,OAAO,EAIL,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,EAC3B,MAAM,iBAAiB,CAAC;AAGzB,MAAM,MAAM,4BAA4B,GAAG,qBAAqB,GAAG;IACjE,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,KAAK,KAAK,IAAI,CAAC;IACxE,IAAI,EAAE,UAAU,GAAG,OAAO,GAAG,QAAQ,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG,oBAAoB,GAAG;IAC/D,WAAW,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,CAAC;IAC5C,aAAa,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,OAAO,CAAC;IACjD,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,gBAAgB;AAChB,eAAO,MAAM,oBAAoB,GAAI,SAAS,qBAAqB,KAAG,oBA6ErE,CAAC;AAEF,eAAO,MAAM,2BAA2B,GAAI,SAAS,4BAA4B,KAAG,2BA+BnF,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{createA11yControl as e}from"./a11y-control.js";import{
|
|
1
|
+
import{createA11yControl as e}from"./a11y-control.js";import{createAssistiveState as t,createFieldControlBase as n}from"./field-control.js";import{createPressControl as r}from"./press-control.js";import{computed as i,signal as a,watch as o}from"@vielzeug/stateit";var s=e=>{let r=a(``),s=a(!!e.checked.value),c=a(!!e.indeterminate?.value),l=t({error:e.error,helper:e.helper});o(e.checked,e=>{s.value=!!e},{immediate:!0}),e.indeterminate&&o(e.indeterminate,e=>{c.value=!!e},{immediate:!0});let{base:u,triggerValidation:d}=n(e,{toFormValue:e=>e,value:i(()=>c.value?null:s.value?e.value.value??``:null)});o(e.value,e=>{r.value=String(e??``)},{immediate:!0});let f=t=>({checked:s.value,originalEvent:t,value:e.value.value??``}),p=t=>{if(!u.disabled.value){if(e.group){c.value=!1,e.group.toggle(e.value.value??``,t),e.onToggle?.(f(t));return}e.clearIndeterminateFirst&&c.value||(s.value=!s.value),c.value=!1,e.onToggle?.(f(t))}};return{...u,assistive:l,checked:s,indeterminate:c,toggle:p,triggerValidation:d,value:r}},c=t=>{let n=s(t),i=e({checked:()=>t.role===`checkbox`&&n.indeterminate.value?`mixed`:n.checked.value?`true`:`false`,helperText:()=>n.assistive.value.errorText||n.assistive.value.helperText,helperTone:()=>n.assistive.value.errorText?`error`:`default`,invalid:()=>!!n.assistive.value.errorText,role:t.role}),a=r({disabled:()=>n.disabled.value,onPress:e=>{if(t.onPress){t.onPress(n,e);return}n.toggle(e)}});return{...n,handleClick:a.handleClick,handleKeydown:a.handleKeydown,helperId:i.helperId,labelId:i.labelId}};export{c as createCheckableFieldControl};
|
|
2
2
|
//# sourceMappingURL=checkable-control.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checkable-control.js","names":[],"sources":["../../src/controls/checkable-control.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"checkable-control.js","names":[],"sources":["../../src/controls/checkable-control.ts"],"sourcesContent":["import { computed, signal, watch } from '@vielzeug/stateit';\n\nimport { createA11yControl } from './a11y-control';\nimport {\n createAssistiveState,\n createFieldControlBase,\n type CheckableChangePayload,\n type CheckableStateHandle,\n type CheckableStateOptions,\n} from './field-control';\nimport { createPressControl } from './press-control';\n\nexport type CheckableFieldControlOptions = CheckableStateOptions & {\n onPress?: (control: CheckableStateHandle, originalEvent: Event) => void;\n role: 'checkbox' | 'radio' | 'switch';\n};\n\nexport type CheckableFieldControlHandle = CheckableStateHandle & {\n handleClick: (event: MouseEvent) => boolean;\n handleKeydown: (event: KeyboardEvent) => boolean;\n helperId: string;\n labelId: string;\n};\n\n/** @internal */\nexport const createCheckableState = (options: CheckableStateOptions): CheckableStateHandle => {\n const value = signal('');\n const checked = signal(Boolean(options.checked.value));\n const indeterminate = signal(Boolean(options.indeterminate?.value));\n const assistive = createAssistiveState({ error: options.error, helper: options.helper });\n\n watch(\n options.checked,\n (next) => {\n checked.value = Boolean(next);\n },\n { immediate: true },\n );\n\n if (options.indeterminate) {\n watch(\n options.indeterminate,\n (next) => {\n indeterminate.value = Boolean(next);\n },\n { immediate: true },\n );\n }\n\n const { base, triggerValidation } = createFieldControlBase(options, {\n toFormValue: (nextValue: string | null) => nextValue,\n value: computed(() => {\n if (indeterminate.value) return null;\n\n return checked.value ? (options.value.value ?? '') : null;\n }),\n });\n\n watch(\n options.value,\n (next) => {\n value.value = String(next ?? '');\n },\n { immediate: true },\n );\n\n const createPayload = (event: Event): CheckableChangePayload => ({\n checked: checked.value,\n originalEvent: event,\n value: options.value.value ?? '',\n });\n\n const toggle = (event: Event): void => {\n if (base.disabled.value) return;\n\n if (options.group) {\n indeterminate.value = false;\n options.group.toggle(options.value.value ?? '', event);\n options.onToggle?.(createPayload(event));\n\n return;\n }\n\n if (options.clearIndeterminateFirst && indeterminate.value) {\n indeterminate.value = false;\n } else {\n checked.value = !checked.value;\n indeterminate.value = false;\n }\n\n options.onToggle?.(createPayload(event));\n };\n\n return {\n ...base,\n assistive,\n checked,\n indeterminate,\n toggle,\n triggerValidation,\n value,\n };\n};\n\nexport const createCheckableFieldControl = (options: CheckableFieldControlOptions): CheckableFieldControlHandle => {\n const control = createCheckableState(options);\n const a11y = createA11yControl({\n checked: () =>\n options.role === 'checkbox' && control.indeterminate.value ? 'mixed' : control.checked.value ? 'true' : 'false',\n helperText: () => control.assistive.value.errorText || control.assistive.value.helperText,\n helperTone: () => (control.assistive.value.errorText ? 'error' : 'default'),\n invalid: () => Boolean(control.assistive.value.errorText),\n role: options.role,\n });\n\n const press = createPressControl({\n disabled: () => control.disabled.value,\n onPress: (originalEvent) => {\n if (options.onPress) {\n options.onPress(control, originalEvent);\n\n return;\n }\n\n control.toggle(originalEvent);\n },\n });\n\n return {\n ...control,\n handleClick: press.handleClick,\n handleKeydown: press.handleKeydown,\n helperId: a11y.helperId,\n labelId: a11y.labelId,\n };\n};\n"],"mappings":"wQAyBA,IAAa,EAAwB,GAAyD,CAC5F,IAAM,EAAQ,EAAO,EAAE,EACjB,EAAU,EAAO,EAAQ,EAAQ,QAAQ,KAAM,EAC/C,EAAgB,EAAO,EAAQ,EAAQ,eAAe,KAAM,EAC5D,EAAY,EAAqB,CAAE,MAAO,EAAQ,MAAO,OAAQ,EAAQ,MAAO,CAAC,EAEvF,EACE,EAAQ,QACP,GAAS,CACR,EAAQ,MAAQ,EAAQ,CAC1B,EACA,CAAE,UAAW,EAAK,CACpB,EAEI,EAAQ,eACV,EACE,EAAQ,cACP,GAAS,CACR,EAAc,MAAQ,EAAQ,CAChC,EACA,CAAE,UAAW,EAAK,CACpB,EAGF,GAAM,CAAE,OAAM,qBAAsB,EAAuB,EAAS,CAClE,YAAc,GAA6B,EAC3C,MAAO,MACD,EAAc,MAAc,KAEzB,EAAQ,MAAS,EAAQ,MAAM,OAAS,GAAM,IACtD,CACH,CAAC,EAED,EACE,EAAQ,MACP,GAAS,CACR,EAAM,MAAQ,OAAO,GAAQ,EAAE,CACjC,EACA,CAAE,UAAW,EAAK,CACpB,EAEA,IAAM,EAAiB,IAA0C,CAC/D,QAAS,EAAQ,MACjB,cAAe,EACf,MAAO,EAAQ,MAAM,OAAS,EAChC,GAEM,EAAU,GAAuB,CACjC,MAAK,SAAS,MAElB,IAAI,EAAQ,MAAO,CACjB,EAAc,MAAQ,GACtB,EAAQ,MAAM,OAAO,EAAQ,MAAM,OAAS,GAAI,CAAK,EACrD,EAAQ,WAAW,EAAc,CAAK,CAAC,EAEvC,MACF,CAEI,EAAQ,yBAA2B,EAAc,QAGnD,EAAQ,MAAQ,CAAC,EAAQ,OAFzB,EAAc,MAAQ,GAMxB,EAAQ,WAAW,EAAc,CAAK,CAAC,CATvC,CAUF,EAEA,MAAO,CACL,GAAG,EACH,YACA,UACA,gBACA,SACA,oBACA,OACF,CACF,EAEa,EAA+B,GAAuE,CACjH,IAAM,EAAU,EAAqB,CAAO,EACtC,EAAO,EAAkB,CAC7B,YACE,EAAQ,OAAS,YAAc,EAAQ,cAAc,MAAQ,QAAU,EAAQ,QAAQ,MAAQ,OAAS,QAC1G,eAAkB,EAAQ,UAAU,MAAM,WAAa,EAAQ,UAAU,MAAM,WAC/E,eAAmB,EAAQ,UAAU,MAAM,UAAY,QAAU,UACjE,YAAe,EAAQ,EAAQ,UAAU,MAAM,UAC/C,KAAM,EAAQ,IAChB,CAAC,EAEK,EAAQ,EAAmB,CAC/B,aAAgB,EAAQ,SAAS,MACjC,QAAU,GAAkB,CAC1B,GAAI,EAAQ,QAAS,CACnB,EAAQ,QAAQ,EAAS,CAAa,EAEtC,MACF,CAEA,EAAQ,OAAO,CAAa,CAC9B,CACF,CAAC,EAED,MAAO,CACL,GAAG,EACH,YAAa,EAAM,YACnB,cAAe,EAAM,cACrB,SAAU,EAAK,SACf,QAAS,EAAK,OAChB,CACF"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require(`./field-control.cjs`);let t=require(`@vielzeug/stateit`);var n=e=>e?e.split(`,`).map(e=>e.trim()).filter(Boolean):[],r=r=>{let i=(0,t.signal)([]),a=(0,t.computed)(()=>!!r.multiple?.value),o=(0,t.computed)(()=>a.value?i.value.join(`,`):i.value[0]??``),s=e=>{let t=a.value?e:e.slice(0,1);return[...new Set(t.map(e=>String(e??``)).filter(Boolean))]},c=e=>{i.value=s(e)},l=()=>{c([])},u=e=>{i.value=i.value.filter(t=>t!==e)},d=e=>{if(a.value){if(i.value.includes(e))return;c([...i.value,e]);return}c([e])},f=e=>{if(a.value){if(i.value.includes(e)){u(e);return}c([...i.value,e]);return}c([e])},p=e=>{let t=n(typeof e==`string`?e:String(e??``));t.length===i.value.length&&t.every((e,t)=>e===i.value[t])||c(t)},{base:m,triggerValidation:h}=e.createFieldControlBase(r,{value:o}),g=e.createAssistiveState({error:r.error,helper:r.helper});return(0,t.watch)(r.value,e=>{p(e)},{immediate:!0}),r.multiple&&(0,t.watch)(r.multiple,()=>p(r.value.value)),{...m,assistive:g,clear:l,formValue:o,removeValue:u,selectedValues:i,selectValue:d,setValues:c,toggleValue:f,triggerValidation:h}};exports.createChoiceField=r;
|
|
2
|
+
//# sourceMappingURL=choice-field-control.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"choice-field-control.cjs","names":[],"sources":["../../src/controls/choice-field-control.ts"],"sourcesContent":["import { computed, signal, watch } from '@vielzeug/stateit';\n\nimport {\n createAssistiveState,\n createFieldControlBase,\n type ChoiceFieldHandle,\n type ChoiceFieldOptions,\n} from './field-control';\n\nconst parseChoiceFieldValues = (value: string | undefined): string[] => {\n if (!value) return [];\n\n return value\n .split(',')\n .map((entry) => entry.trim())\n .filter(Boolean);\n};\n\nexport const createChoiceField = (options: ChoiceFieldOptions): ChoiceFieldHandle => {\n const selectedValues = signal<string[]>([]);\n const isMultiple = computed(() => Boolean(options.multiple?.value));\n const formValue = computed(() =>\n isMultiple.value ? selectedValues.value.join(',') : (selectedValues.value[0] ?? ''),\n );\n\n const normalizeSelectedValues = (values: string[]): string[] => {\n const normalized = isMultiple.value ? values : values.slice(0, 1);\n\n return [...new Set(normalized.map((entry) => String(entry ?? '')).filter(Boolean))];\n };\n\n const setValues = (values: string[]): void => {\n selectedValues.value = normalizeSelectedValues(values);\n };\n\n const clear = (): void => {\n setValues([]);\n };\n\n const removeValue = (value: string): void => {\n selectedValues.value = selectedValues.value.filter((current) => current !== value);\n };\n\n const selectValue = (value: string): void => {\n if (isMultiple.value) {\n if (selectedValues.value.includes(value)) return;\n\n setValues([...selectedValues.value, value]);\n\n return;\n }\n\n setValues([value]);\n };\n\n const toggleValue = (value: string): void => {\n if (isMultiple.value) {\n if (selectedValues.value.includes(value)) {\n removeValue(value);\n\n return;\n }\n\n setValues([...selectedValues.value, value]);\n\n return;\n }\n\n setValues([value]);\n };\n\n const syncControlledValue = (nextValue: unknown): void => {\n const values = parseChoiceFieldValues(typeof nextValue === 'string' ? nextValue : String(nextValue ?? ''));\n\n if (\n values.length === selectedValues.value.length &&\n values.every((value, index) => value === selectedValues.value[index])\n ) {\n return;\n }\n\n setValues(values);\n };\n\n const { base, triggerValidation } = createFieldControlBase(options, { value: formValue });\n\n const assistive = createAssistiveState({\n error: options.error,\n helper: options.helper,\n });\n\n watch(\n options.value,\n (next) => {\n syncControlledValue(next);\n },\n { immediate: true },\n );\n\n if (options.multiple) {\n watch(options.multiple, () => syncControlledValue(options.value.value));\n }\n\n return {\n ...base,\n assistive,\n clear,\n formValue,\n removeValue,\n selectedValues,\n selectValue,\n setValues,\n toggleValue,\n triggerValidation,\n };\n};\n"],"mappings":"0EASA,IAAM,EAA0B,GACzB,EAEE,EACJ,MAAM,GAAG,EACT,IAAK,GAAU,EAAM,KAAK,CAAC,EAC3B,OAAO,OAAO,EALE,CAAC,EAQT,EAAqB,GAAmD,CACnF,IAAM,GAAA,EAAA,EAAA,QAAkC,CAAC,CAAC,EACpC,GAAA,EAAA,EAAA,cAA4B,EAAQ,EAAQ,UAAU,KAAM,EAC5D,GAAA,EAAA,EAAA,cACJ,EAAW,MAAQ,EAAe,MAAM,KAAK,GAAG,EAAK,EAAe,MAAM,IAAM,EAClF,EAEM,EAA2B,GAA+B,CAC9D,IAAM,EAAa,EAAW,MAAQ,EAAS,EAAO,MAAM,EAAG,CAAC,EAEhE,MAAO,CAAC,GAAG,IAAI,IAAI,EAAW,IAAK,GAAU,OAAO,GAAS,EAAE,CAAC,EAAE,OAAO,OAAO,CAAC,CAAC,CACpF,EAEM,EAAa,GAA2B,CAC5C,EAAe,MAAQ,EAAwB,CAAM,CACvD,EAEM,MAAoB,CACxB,EAAU,CAAC,CAAC,CACd,EAEM,EAAe,GAAwB,CAC3C,EAAe,MAAQ,EAAe,MAAM,OAAQ,GAAY,IAAY,CAAK,CACnF,EAEM,EAAe,GAAwB,CAC3C,GAAI,EAAW,MAAO,CACpB,GAAI,EAAe,MAAM,SAAS,CAAK,EAAG,OAE1C,EAAU,CAAC,GAAG,EAAe,MAAO,CAAK,CAAC,EAE1C,MACF,CAEA,EAAU,CAAC,CAAK,CAAC,CACnB,EAEM,EAAe,GAAwB,CAC3C,GAAI,EAAW,MAAO,CACpB,GAAI,EAAe,MAAM,SAAS,CAAK,EAAG,CACxC,EAAY,CAAK,EAEjB,MACF,CAEA,EAAU,CAAC,GAAG,EAAe,MAAO,CAAK,CAAC,EAE1C,MACF,CAEA,EAAU,CAAC,CAAK,CAAC,CACnB,EAEM,EAAuB,GAA6B,CACxD,IAAM,EAAS,EAAuB,OAAO,GAAc,SAAW,EAAY,OAAO,GAAa,EAAE,CAAC,EAGvG,EAAO,SAAW,EAAe,MAAM,QACvC,EAAO,OAAO,EAAO,IAAU,IAAU,EAAe,MAAM,EAAM,GAKtE,EAAU,CAAM,CAClB,EAEM,CAAE,OAAM,qBAAsB,EAAA,uBAAuB,EAAS,CAAE,MAAO,CAAU,CAAC,EAElF,EAAY,EAAA,qBAAqB,CACrC,MAAO,EAAQ,MACf,OAAQ,EAAQ,MAClB,CAAC,EAcD,OAZA,EAAA,EAAA,OACE,EAAQ,MACP,GAAS,CACR,EAAoB,CAAI,CAC1B,EACA,CAAE,UAAW,EAAK,CACpB,EAEI,EAAQ,WACV,EAAA,EAAA,OAAM,EAAQ,aAAgB,EAAoB,EAAQ,MAAM,KAAK,CAAC,EAGjE,CACL,GAAG,EACH,YACA,QACA,YACA,cACA,iBACA,cACA,YACA,cACA,mBACF,CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"choice-field-control.d.ts","sourceRoot":"","sources":["../../src/controls/choice-field-control.ts"],"names":[],"mappings":"AAEA,OAAO,EAGL,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACxB,MAAM,iBAAiB,CAAC;AAWzB,eAAO,MAAM,iBAAiB,GAAI,SAAS,kBAAkB,KAAG,iBAiG/D,CAAC"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{createAssistiveState as e,createFieldControlBase as t}from"./field-control.js";import{computed as n,signal as r,watch as i}from"@vielzeug/stateit";var a=e=>e?e.split(`,`).map(e=>e.trim()).filter(Boolean):[],o=o=>{let s=r([]),c=n(()=>!!o.multiple?.value),l=n(()=>c.value?s.value.join(`,`):s.value[0]??``),u=e=>{let t=c.value?e:e.slice(0,1);return[...new Set(t.map(e=>String(e??``)).filter(Boolean))]},d=e=>{s.value=u(e)},f=()=>{d([])},p=e=>{s.value=s.value.filter(t=>t!==e)},m=e=>{if(c.value){if(s.value.includes(e))return;d([...s.value,e]);return}d([e])},h=e=>{if(c.value){if(s.value.includes(e)){p(e);return}d([...s.value,e]);return}d([e])},g=e=>{let t=a(typeof e==`string`?e:String(e??``));t.length===s.value.length&&t.every((e,t)=>e===s.value[t])||d(t)},{base:_,triggerValidation:v}=t(o,{value:l}),y=e({error:o.error,helper:o.helper});return i(o.value,e=>{g(e)},{immediate:!0}),o.multiple&&i(o.multiple,()=>g(o.value.value)),{..._,assistive:y,clear:f,formValue:l,removeValue:p,selectedValues:s,selectValue:m,setValues:d,toggleValue:h,triggerValidation:v}};export{o as createChoiceField};
|
|
2
|
+
//# sourceMappingURL=choice-field-control.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"choice-field-control.js","names":[],"sources":["../../src/controls/choice-field-control.ts"],"sourcesContent":["import { computed, signal, watch } from '@vielzeug/stateit';\n\nimport {\n createAssistiveState,\n createFieldControlBase,\n type ChoiceFieldHandle,\n type ChoiceFieldOptions,\n} from './field-control';\n\nconst parseChoiceFieldValues = (value: string | undefined): string[] => {\n if (!value) return [];\n\n return value\n .split(',')\n .map((entry) => entry.trim())\n .filter(Boolean);\n};\n\nexport const createChoiceField = (options: ChoiceFieldOptions): ChoiceFieldHandle => {\n const selectedValues = signal<string[]>([]);\n const isMultiple = computed(() => Boolean(options.multiple?.value));\n const formValue = computed(() =>\n isMultiple.value ? selectedValues.value.join(',') : (selectedValues.value[0] ?? ''),\n );\n\n const normalizeSelectedValues = (values: string[]): string[] => {\n const normalized = isMultiple.value ? values : values.slice(0, 1);\n\n return [...new Set(normalized.map((entry) => String(entry ?? '')).filter(Boolean))];\n };\n\n const setValues = (values: string[]): void => {\n selectedValues.value = normalizeSelectedValues(values);\n };\n\n const clear = (): void => {\n setValues([]);\n };\n\n const removeValue = (value: string): void => {\n selectedValues.value = selectedValues.value.filter((current) => current !== value);\n };\n\n const selectValue = (value: string): void => {\n if (isMultiple.value) {\n if (selectedValues.value.includes(value)) return;\n\n setValues([...selectedValues.value, value]);\n\n return;\n }\n\n setValues([value]);\n };\n\n const toggleValue = (value: string): void => {\n if (isMultiple.value) {\n if (selectedValues.value.includes(value)) {\n removeValue(value);\n\n return;\n }\n\n setValues([...selectedValues.value, value]);\n\n return;\n }\n\n setValues([value]);\n };\n\n const syncControlledValue = (nextValue: unknown): void => {\n const values = parseChoiceFieldValues(typeof nextValue === 'string' ? nextValue : String(nextValue ?? ''));\n\n if (\n values.length === selectedValues.value.length &&\n values.every((value, index) => value === selectedValues.value[index])\n ) {\n return;\n }\n\n setValues(values);\n };\n\n const { base, triggerValidation } = createFieldControlBase(options, { value: formValue });\n\n const assistive = createAssistiveState({\n error: options.error,\n helper: options.helper,\n });\n\n watch(\n options.value,\n (next) => {\n syncControlledValue(next);\n },\n { immediate: true },\n );\n\n if (options.multiple) {\n watch(options.multiple, () => syncControlledValue(options.value.value));\n }\n\n return {\n ...base,\n assistive,\n clear,\n formValue,\n removeValue,\n selectedValues,\n selectValue,\n setValues,\n toggleValue,\n triggerValidation,\n };\n};\n"],"mappings":"0JASA,IAAM,EAA0B,GACzB,EAEE,EACJ,MAAM,GAAG,EACT,IAAK,GAAU,EAAM,KAAK,CAAC,EAC3B,OAAO,OAAO,EALE,CAAC,EAQT,EAAqB,GAAmD,CACnF,IAAM,EAAiB,EAAiB,CAAC,CAAC,EACpC,EAAa,MAAe,EAAQ,EAAQ,UAAU,KAAM,EAC5D,EAAY,MAChB,EAAW,MAAQ,EAAe,MAAM,KAAK,GAAG,EAAK,EAAe,MAAM,IAAM,EAClF,EAEM,EAA2B,GAA+B,CAC9D,IAAM,EAAa,EAAW,MAAQ,EAAS,EAAO,MAAM,EAAG,CAAC,EAEhE,MAAO,CAAC,GAAG,IAAI,IAAI,EAAW,IAAK,GAAU,OAAO,GAAS,EAAE,CAAC,EAAE,OAAO,OAAO,CAAC,CAAC,CACpF,EAEM,EAAa,GAA2B,CAC5C,EAAe,MAAQ,EAAwB,CAAM,CACvD,EAEM,MAAoB,CACxB,EAAU,CAAC,CAAC,CACd,EAEM,EAAe,GAAwB,CAC3C,EAAe,MAAQ,EAAe,MAAM,OAAQ,GAAY,IAAY,CAAK,CACnF,EAEM,EAAe,GAAwB,CAC3C,GAAI,EAAW,MAAO,CACpB,GAAI,EAAe,MAAM,SAAS,CAAK,EAAG,OAE1C,EAAU,CAAC,GAAG,EAAe,MAAO,CAAK,CAAC,EAE1C,MACF,CAEA,EAAU,CAAC,CAAK,CAAC,CACnB,EAEM,EAAe,GAAwB,CAC3C,GAAI,EAAW,MAAO,CACpB,GAAI,EAAe,MAAM,SAAS,CAAK,EAAG,CACxC,EAAY,CAAK,EAEjB,MACF,CAEA,EAAU,CAAC,GAAG,EAAe,MAAO,CAAK,CAAC,EAE1C,MACF,CAEA,EAAU,CAAC,CAAK,CAAC,CACnB,EAEM,EAAuB,GAA6B,CACxD,IAAM,EAAS,EAAuB,OAAO,GAAc,SAAW,EAAY,OAAO,GAAa,EAAE,CAAC,EAGvG,EAAO,SAAW,EAAe,MAAM,QACvC,EAAO,OAAO,EAAO,IAAU,IAAU,EAAe,MAAM,EAAM,GAKtE,EAAU,CAAM,CAClB,EAEM,CAAE,OAAM,qBAAsB,EAAuB,EAAS,CAAE,MAAO,CAAU,CAAC,EAElF,EAAY,EAAqB,CACrC,MAAO,EAAQ,MACf,OAAQ,EAAQ,MAClB,CAAC,EAcD,OAZA,EACE,EAAQ,MACP,GAAS,CACR,EAAoB,CAAI,CAC1B,EACA,CAAE,UAAW,EAAK,CACpB,EAEI,EAAQ,UACV,EAAM,EAAQ,aAAgB,EAAoB,EAAQ,MAAM,KAAK,CAAC,EAGjE,CACL,GAAG,EACH,YACA,QACA,YACA,cACA,iBACA,cACA,YACA,cACA,mBACF,CACF"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require(`../runtime
|
|
1
|
+
const e=require(`../runtime.cjs`),t=require(`../internal.cjs`),n=require(`../form.cjs`),r=require(`./internal/control-state.cjs`);let i=require(`@vielzeug/stateit`);var a=(e,n)=>{let r=`${e}-${n&&n.trim()?n.trim():t.createId().replace(/^cft-/,``)}`,i=`label-${r}`;return{errorId:`error-${r}`,fieldId:r,helperId:`helper-${r}`,labelInsetId:i,labelOutsideId:`${i}-outside`}},o=(e,t)=>{let i=r.createControlState(e),o=a(e.prefix,e.name?.value),s={disabled:i.disabled,errorId:o.errorId,fieldId:o.fieldId,helperId:o.helperId,labelInsetId:o.labelInsetId,labelOutsideId:o.labelOutsideId},c=n.defineField({...t,disabled:t.disabled??s.disabled});return{base:s,triggerValidation:e=>i.triggerValidation(c,e)}},s=e=>(0,i.computed)(()=>{let t=e.value?.value??``,n=e.error?.value??``,r=e.helper?.value??``,i=e.maxLength?.value,a=Number(i),o=Number.isFinite(a)&&a>0?a:null,s=o!==null,c=s?`${t.length} / ${o}`:``,l=s?t.length/o:0;return{counterAtLimit:s?l>=1:!1,counterNearLimit:s?l>=.9&&l<1:!1,counterText:c,errorText:n,hasCounter:s,helperText:r}}),c=t=>{let{element:n,onBlur:r,onChange:i,onInput:a,triggerValidation:o}=t,s=[];return a&&s.push(e.listen(n,`input`,e=>{e.stopPropagation(),a(e,n.value)})),s.push(e.listen(n,`change`,e=>{e.stopPropagation(),i?.(e,n.value),o?.(`change`)})),s.push(e.listen(n,`blur`,e=>{r?.(e),o?.(`blur`)})),()=>{for(let e of s)e()}};exports.createAssistiveState=s,exports.createFieldControlBase=o,exports.mountTextFieldLifecycle=c;
|
|
2
2
|
//# sourceMappingURL=field-control.cjs.map
|