@vielzeug/ore 1.3.0 → 2.0.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/README.md +11 -8
- package/dist/_component-class.cjs +2 -0
- package/dist/_component-class.cjs.map +1 -0
- package/dist/_component-class.d.ts +2 -0
- package/dist/_component-class.d.ts.map +1 -0
- package/dist/_component-class.js +2 -0
- package/dist/_component-class.js.map +1 -0
- package/dist/_dev.cjs +1 -1
- package/dist/_dev.cjs.map +1 -1
- package/dist/_dev.js +1 -1
- package/dist/_dev.js.map +1 -1
- package/dist/base-element.cjs +1 -1
- package/dist/base-element.cjs.map +1 -1
- package/dist/base-element.d.ts +9 -15
- package/dist/base-element.d.ts.map +1 -1
- package/dist/base-element.js +1 -1
- package/dist/base-element.js.map +1 -1
- package/dist/component-types.d.ts +3 -14
- package/dist/component-types.d.ts.map +1 -1
- package/dist/context.cjs +1 -1
- package/dist/context.cjs.map +1 -1
- package/dist/context.d.ts +13 -0
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +1 -1
- package/dist/context.js.map +1 -1
- package/dist/define.cjs +1 -1
- package/dist/define.cjs.map +1 -1
- package/dist/define.d.ts +6 -5
- package/dist/define.d.ts.map +1 -1
- package/dist/define.js +1 -1
- package/dist/define.js.map +1 -1
- package/dist/directives/classMap.cjs.map +1 -1
- package/dist/directives/each.cjs +1 -1
- package/dist/directives/each.cjs.map +1 -1
- package/dist/directives/each.d.ts +1 -1
- 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/live.cjs +1 -1
- package/dist/directives/live.cjs.map +1 -1
- package/dist/directives/live.d.ts +10 -12
- package/dist/directives/live.d.ts.map +1 -1
- package/dist/directives/live.js +1 -1
- package/dist/directives/live.js.map +1 -1
- package/dist/directives/styleMap.cjs.map +1 -1
- package/dist/directives/styleMap.d.ts +1 -1
- package/dist/directives/styleMap.js.map +1 -1
- package/dist/directives/unsafe-html.cjs +2 -0
- package/dist/directives/unsafe-html.cjs.map +1 -0
- package/dist/directives/unsafe-html.d.ts +14 -0
- package/dist/directives/unsafe-html.d.ts.map +1 -0
- package/dist/directives/unsafe-html.js +2 -0
- package/dist/directives/unsafe-html.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 +1 -1
- 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 -2
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.d.ts +6 -4
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +2 -2
- package/dist/errors.js.map +1 -1
- package/dist/forms/field.cjs +1 -1
- package/dist/forms/field.cjs.map +1 -1
- package/dist/forms/field.d.ts +5 -1
- package/dist/forms/field.d.ts.map +1 -1
- package/dist/forms/field.js +1 -1
- package/dist/forms/field.js.map +1 -1
- package/dist/host-bind.cjs.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +9 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +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.map +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.map +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 +1 -1
- package/dist/observers/mutation-observe.cjs.map +1 -1
- package/dist/observers/mutation-observe.d.ts.map +1 -1
- package/dist/observers/mutation-observe.js +1 -1
- package/dist/observers/mutation-observe.js.map +1 -1
- package/dist/observers/resize-observe.cjs +1 -1
- package/dist/observers/resize-observe.cjs.map +1 -1
- package/dist/observers/resize-observe.d.ts.map +1 -1
- package/dist/observers/resize-observe.js +1 -1
- package/dist/observers/resize-observe.js.map +1 -1
- package/dist/ore.cjs +2 -2
- package/dist/ore.cjs.map +1 -1
- package/dist/ore.iife.js +2 -2
- package/dist/ore.iife.js.map +1 -1
- package/dist/ore.js +2 -2
- package/dist/ore.js.map +1 -1
- package/dist/props.cjs +1 -1
- package/dist/props.cjs.map +1 -1
- package/dist/props.d.ts +1 -6
- package/dist/props.d.ts.map +1 -1
- package/dist/props.js +1 -1
- package/dist/props.js.map +1 -1
- package/dist/runtime.cjs +1 -1
- package/dist/runtime.cjs.map +1 -1
- package/dist/runtime.d.ts +7 -10
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +1 -1
- package/dist/runtime.js.map +1 -1
- package/dist/slots.cjs +1 -1
- package/dist/slots.cjs.map +1 -1
- package/dist/slots.d.ts.map +1 -1
- package/dist/slots.js +1 -1
- package/dist/slots.js.map +1 -1
- package/dist/template/binding-types.cjs +1 -0
- package/dist/template/binding-types.d.ts +59 -0
- package/dist/template/binding-types.d.ts.map +1 -0
- package/dist/template/binding-types.js +1 -0
- package/dist/template/bindings.cjs +1 -1
- package/dist/template/bindings.cjs.map +1 -1
- package/dist/template/bindings.d.ts +18 -3
- 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 +0 -4
- 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/template/instantiator.cjs +1 -1
- package/dist/template/instantiator.cjs.map +1 -1
- package/dist/template/instantiator.d.ts +6 -1
- package/dist/template/instantiator.d.ts.map +1 -1
- package/dist/template/instantiator.js +1 -1
- package/dist/template/instantiator.js.map +1 -1
- package/dist/template/result.cjs +2 -0
- package/dist/template/result.cjs.map +1 -0
- package/dist/template/result.d.ts +42 -0
- package/dist/template/result.d.ts.map +1 -0
- package/dist/template/result.js +2 -0
- package/dist/template/result.js.map +1 -0
- package/dist/testing/flush.cjs +1 -1
- package/dist/testing/flush.cjs.map +1 -1
- package/dist/testing/flush.d.ts +4 -4
- package/dist/testing/flush.js +1 -1
- package/dist/testing/flush.js.map +1 -1
- package/dist/testing/form-internals-polyfill.cjs +1 -1
- package/dist/testing/form-internals-polyfill.cjs.map +1 -1
- package/dist/testing/form-internals-polyfill.d.ts +9 -7
- package/dist/testing/form-internals-polyfill.d.ts.map +1 -1
- package/dist/testing/form-internals-polyfill.js +1 -1
- package/dist/testing/form-internals-polyfill.js.map +1 -1
- package/dist/testing/index.d.ts +14 -9
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/mount.cjs +1 -1
- package/dist/testing/mount.cjs.map +1 -1
- package/dist/testing/mount.d.ts +6 -9
- package/dist/testing/mount.d.ts.map +1 -1
- package/dist/testing/mount.js +1 -1
- package/dist/testing/mount.js.map +1 -1
- package/dist/testing/render-hook.cjs +1 -1
- package/dist/testing/render-hook.cjs.map +1 -1
- package/dist/testing/render-hook.js +1 -1
- package/dist/testing/render-hook.js.map +1 -1
- package/dist/testing/reset.cjs +2 -0
- package/dist/testing/reset.cjs.map +1 -0
- package/dist/testing/reset.d.ts +12 -0
- package/dist/testing/reset.d.ts.map +1 -0
- package/dist/testing/reset.js +2 -0
- package/dist/testing/reset.js.map +1 -0
- package/dist/testing.cjs +1 -1
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.js +1 -1
- package/dist/testing.js.map +1 -1
- package/dist/utils/brand.cjs +2 -0
- package/dist/utils/brand.cjs.map +1 -0
- package/dist/utils/brand.d.ts +16 -0
- package/dist/utils/brand.d.ts.map +1 -0
- package/dist/utils/brand.js +2 -0
- package/dist/utils/brand.js.map +1 -0
- package/dist/utils/css.cjs +1 -1
- package/dist/utils/css.cjs.map +1 -1
- package/dist/utils/css.d.ts.map +1 -1
- package/dist/utils/css.js +1 -1
- package/dist/utils/css.js.map +1 -1
- package/dist/utils/dom.cjs +1 -1
- package/dist/utils/dom.cjs.map +1 -1
- package/dist/utils/dom.d.ts +3 -5
- package/dist/utils/dom.d.ts.map +1 -1
- package/dist/utils/dom.js +1 -1
- package/dist/utils/dom.js.map +1 -1
- package/dist/utils/emit.cjs.map +1 -1
- package/dist/utils/emit.d.ts +10 -3
- package/dist/utils/emit.d.ts.map +1 -1
- package/dist/utils/emit.js.map +1 -1
- package/package.json +15 -25
- package/dist/aria.cjs +0 -2
- package/dist/aria.cjs.map +0 -1
- package/dist/aria.d.ts +0 -21
- package/dist/aria.d.ts.map +0 -1
- package/dist/aria.js +0 -2
- package/dist/aria.js.map +0 -1
- package/dist/directives/index.d.ts +0 -37
- package/dist/directives/index.d.ts.map +0 -1
- package/dist/directives/model.cjs +0 -2
- package/dist/directives/model.cjs.map +0 -1
- package/dist/directives/model.d.ts +0 -28
- package/dist/directives/model.d.ts.map +0 -1
- package/dist/directives/model.js +0 -2
- package/dist/directives/model.js.map +0 -1
- package/dist/directives/raw.cjs +0 -2
- package/dist/directives/raw.cjs.map +0 -1
- package/dist/directives/raw.d.ts +0 -16
- package/dist/directives/raw.d.ts.map +0 -1
- package/dist/directives/raw.js +0 -2
- package/dist/directives/raw.js.map +0 -1
- package/dist/directives.cjs +0 -1
- package/dist/directives.js +0 -1
- package/dist/forms/context.cjs +0 -2
- package/dist/forms/context.cjs.map +0 -1
- package/dist/forms/context.d.ts +0 -56
- package/dist/forms/context.d.ts.map +0 -1
- package/dist/forms/context.js +0 -2
- package/dist/forms/context.js.map +0 -1
- package/dist/forms/index.d.ts +0 -11
- package/dist/forms/index.d.ts.map +0 -1
- package/dist/forms.cjs +0 -1
- package/dist/forms.js +0 -1
- package/dist/observers/index.d.ts +0 -5
- package/dist/observers/index.d.ts.map +0 -1
- package/dist/observers.cjs +0 -1
- package/dist/observers.js +0 -1
- package/dist/template.cjs +0 -1
- package/dist/template.d.ts +0 -4
- package/dist/template.d.ts.map +0 -1
- package/dist/template.js +0 -1
- package/dist/testing/interactions.cjs +0 -2
- package/dist/testing/interactions.cjs.map +0 -1
- package/dist/testing/interactions.d.ts +0 -27
- package/dist/testing/interactions.d.ts.map +0 -1
- package/dist/testing/interactions.js +0 -2
- package/dist/testing/interactions.js.map +0 -1
- package/dist/types/bindings.cjs +0 -2
- package/dist/types/bindings.cjs.map +0 -1
- package/dist/types/bindings.d.ts +0 -125
- package/dist/types/bindings.d.ts.map +0 -1
- package/dist/types/bindings.js +0 -2
- package/dist/types/bindings.js.map +0 -1
- package/dist/types.cjs +0 -2
- package/dist/types.cjs.map +0 -1
- package/dist/types.d.ts +0 -19
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -2
- package/dist/types.js.map +0 -1
- package/dist/utils/event-modifiers.cjs +0 -2
- package/dist/utils/event-modifiers.cjs.map +0 -1
- package/dist/utils/event-modifiers.d.ts +0 -11
- package/dist/utils/event-modifiers.d.ts.map +0 -1
- package/dist/utils/event-modifiers.js +0 -2
- package/dist/utils/event-modifiers.js.map +0 -1
package/dist/utils/emit.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emit.cjs","names":[],"sources":["../../src/utils/emit.ts"],"sourcesContent":["/**\n * Type-safe custom event emission for components.\n */\n\nimport { getHost } from '../runtime';\n\ntype NoDetail = void | undefined | never;\ntype KeysWithoutDetail<T extends Record<string, unknown>> = {\n [P in keyof T]: [T[P]] extends [NoDetail] ? P : never;\n}[keyof T];\n\
|
|
1
|
+
{"version":3,"file":"emit.cjs","names":[],"sources":["../../src/utils/emit.ts"],"sourcesContent":["/**\n * Type-safe custom event emission for components.\n */\n\nimport { getHost } from '../runtime';\n\ntype NoDetail = void | undefined | never;\ntype KeysWithoutDetail<T extends Record<string, unknown>> = {\n [P in keyof T]: [T[P]] extends [NoDetail] ? P : never;\n}[keyof T];\n\n/**\n * Typed emit function: only declared event names type-check, and `detail` is\n * required exactly when its payload type is non-void. Dynamic event names must\n * be cast at the call site — an intentional speed bump, not a silent escape.\n */\nexport type EmitFn<T extends Record<string, unknown>> = {\n <K extends KeysWithoutDetail<T>>(event: K): boolean;\n <K extends Exclude<keyof T, KeysWithoutDetail<T>>>(event: K, detail: T[K]): boolean;\n};\n\nconst DEFAULT_FIRE_OPTIONS = { bubbles: true, cancelable: true, composed: false };\n\n/**\n * Returns a typed `emit()` function bound to the current component's host element.\n * Call once during `setup()` — the `Emits` type parameter maps event names to\n * their `detail` payload type.\n *\n * Every event is dispatched `cancelable: true`, and `emit()` returns `dispatchEvent`'s\n * own boolean result — `false` when a listener called `preventDefault()`. Components\n * that need to know whether a listener cancelled an event (e.g. to skip a default\n * action) read this return value directly instead of hand-rolling `dispatchEvent`.\n *\n * Events do **not** cross the shadow boundary by default (`composed: false`) — a\n * listener outside the component's shadow root will not observe them. Dispatch a\n * `CustomEvent` with `composed: true` by hand if an event must escape the shadow root.\n *\n * @example\n * ```ts\n * type Events = { close: undefined; change: { value: string } };\n *\n * setup(props) {\n * const emit = useEmit<Events>();\n * emit('close');\n *\n * const notCancelled = emit('change', { value: 'ok' });\n * if (notCancelled) props.value.value = 'ok';\n * }\n * ```\n */\nexport const useEmit = <T extends Record<string, unknown> = Record<string, never>>(): EmitFn<T> => {\n const host = getHost();\n\n return ((event: keyof T, ...rest: unknown[]) => {\n const customEventInit = rest.length > 0 ? { ...DEFAULT_FIRE_OPTIONS, detail: rest[0] } : DEFAULT_FIRE_OPTIONS;\n\n return host.dispatchEvent(new CustomEvent<unknown>(String(event), customEventInit));\n }) as EmitFn<T>;\n};\n"],"mappings":"kCAqBA,IAAM,EAAuB,CAAE,QAAS,GAAM,WAAY,GAAM,SAAU,EAAM,EA6BnE,MAAsF,CACjG,IAAM,EAAO,EAAA,QAAQ,EAErB,QAAS,EAAgB,GAAG,IAAoB,CAC9C,IAAM,EAAkB,EAAK,OAAS,EAAI,CAAE,GAAG,EAAsB,OAAQ,EAAK,EAAG,EAAI,EAEzF,OAAO,EAAK,cAAc,IAAI,YAAqB,OAAO,CAAK,EAAG,CAAe,CAAC,CACpF,EACF"}
|
package/dist/utils/emit.d.ts
CHANGED
|
@@ -5,12 +5,15 @@ type NoDetail = void | undefined | never;
|
|
|
5
5
|
type KeysWithoutDetail<T extends Record<string, unknown>> = {
|
|
6
6
|
[P in keyof T]: [T[P]] extends [NoDetail] ? P : never;
|
|
7
7
|
}[keyof T];
|
|
8
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Typed emit function: only declared event names type-check, and `detail` is
|
|
10
|
+
* required exactly when its payload type is non-void. Dynamic event names must
|
|
11
|
+
* be cast at the call site — an intentional speed bump, not a silent escape.
|
|
12
|
+
*/
|
|
13
|
+
export type EmitFn<T extends Record<string, unknown>> = {
|
|
9
14
|
<K extends KeysWithoutDetail<T>>(event: K): boolean;
|
|
10
15
|
<K extends Exclude<keyof T, KeysWithoutDetail<T>>>(event: K, detail: T[K]): boolean;
|
|
11
16
|
};
|
|
12
|
-
type LooseEmitFn = (event: string, detail?: unknown) => boolean;
|
|
13
|
-
export type EmitFn<T extends Record<string, unknown>> = StrictEmitFn<T> & LooseEmitFn;
|
|
14
17
|
/**
|
|
15
18
|
* Returns a typed `emit()` function bound to the current component's host element.
|
|
16
19
|
* Call once during `setup()` — the `Emits` type parameter maps event names to
|
|
@@ -21,6 +24,10 @@ export type EmitFn<T extends Record<string, unknown>> = StrictEmitFn<T> & LooseE
|
|
|
21
24
|
* that need to know whether a listener cancelled an event (e.g. to skip a default
|
|
22
25
|
* action) read this return value directly instead of hand-rolling `dispatchEvent`.
|
|
23
26
|
*
|
|
27
|
+
* Events do **not** cross the shadow boundary by default (`composed: false`) — a
|
|
28
|
+
* listener outside the component's shadow root will not observe them. Dispatch a
|
|
29
|
+
* `CustomEvent` with `composed: true` by hand if an event must escape the shadow root.
|
|
30
|
+
*
|
|
24
31
|
* @example
|
|
25
32
|
* ```ts
|
|
26
33
|
* type Events = { close: undefined; change: { value: string } };
|
package/dist/utils/emit.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emit.d.ts","sourceRoot":"","sources":["../../src/utils/emit.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,KAAK,QAAQ,GAAG,IAAI,GAAG,SAAS,GAAG,KAAK,CAAC;AACzC,KAAK,iBAAiB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI;KACzD,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,KAAK;CACtD,CAAC,MAAM,CAAC,CAAC,CAAC;AAEX,
|
|
1
|
+
{"version":3,"file":"emit.d.ts","sourceRoot":"","sources":["../../src/utils/emit.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,KAAK,QAAQ,GAAG,IAAI,GAAG,SAAS,GAAG,KAAK,CAAC;AACzC,KAAK,iBAAiB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI;KACzD,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,KAAK;CACtD,CAAC,MAAM,CAAC,CAAC,CAAC;AAEX;;;;GAIG;AACH,MAAM,MAAM,MAAM,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI;IACtD,CAAC,CAAC,SAAS,iBAAiB,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC;IACpD,CAAC,CAAC,SAAS,OAAO,CAAC,MAAM,CAAC,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC;CACrF,CAAC;AAIF;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,eAAO,MAAM,OAAO,GAAI,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,OAAK,MAAM,CAAC,CAAC,CAQ7F,CAAC"}
|
package/dist/utils/emit.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emit.js","names":[],"sources":["../../src/utils/emit.ts"],"sourcesContent":["/**\n * Type-safe custom event emission for components.\n */\n\nimport { getHost } from '../runtime';\n\ntype NoDetail = void | undefined | never;\ntype KeysWithoutDetail<T extends Record<string, unknown>> = {\n [P in keyof T]: [T[P]] extends [NoDetail] ? P : never;\n}[keyof T];\n\
|
|
1
|
+
{"version":3,"file":"emit.js","names":[],"sources":["../../src/utils/emit.ts"],"sourcesContent":["/**\n * Type-safe custom event emission for components.\n */\n\nimport { getHost } from '../runtime';\n\ntype NoDetail = void | undefined | never;\ntype KeysWithoutDetail<T extends Record<string, unknown>> = {\n [P in keyof T]: [T[P]] extends [NoDetail] ? P : never;\n}[keyof T];\n\n/**\n * Typed emit function: only declared event names type-check, and `detail` is\n * required exactly when its payload type is non-void. Dynamic event names must\n * be cast at the call site — an intentional speed bump, not a silent escape.\n */\nexport type EmitFn<T extends Record<string, unknown>> = {\n <K extends KeysWithoutDetail<T>>(event: K): boolean;\n <K extends Exclude<keyof T, KeysWithoutDetail<T>>>(event: K, detail: T[K]): boolean;\n};\n\nconst DEFAULT_FIRE_OPTIONS = { bubbles: true, cancelable: true, composed: false };\n\n/**\n * Returns a typed `emit()` function bound to the current component's host element.\n * Call once during `setup()` — the `Emits` type parameter maps event names to\n * their `detail` payload type.\n *\n * Every event is dispatched `cancelable: true`, and `emit()` returns `dispatchEvent`'s\n * own boolean result — `false` when a listener called `preventDefault()`. Components\n * that need to know whether a listener cancelled an event (e.g. to skip a default\n * action) read this return value directly instead of hand-rolling `dispatchEvent`.\n *\n * Events do **not** cross the shadow boundary by default (`composed: false`) — a\n * listener outside the component's shadow root will not observe them. Dispatch a\n * `CustomEvent` with `composed: true` by hand if an event must escape the shadow root.\n *\n * @example\n * ```ts\n * type Events = { close: undefined; change: { value: string } };\n *\n * setup(props) {\n * const emit = useEmit<Events>();\n * emit('close');\n *\n * const notCancelled = emit('change', { value: 'ok' });\n * if (notCancelled) props.value.value = 'ok';\n * }\n * ```\n */\nexport const useEmit = <T extends Record<string, unknown> = Record<string, never>>(): EmitFn<T> => {\n const host = getHost();\n\n return ((event: keyof T, ...rest: unknown[]) => {\n const customEventInit = rest.length > 0 ? { ...DEFAULT_FIRE_OPTIONS, detail: rest[0] } : DEFAULT_FIRE_OPTIONS;\n\n return host.dispatchEvent(new CustomEvent<unknown>(String(event), customEventInit));\n }) as EmitFn<T>;\n};\n"],"mappings":"wCAqBA,IAAM,EAAuB,CAAE,QAAS,GAAM,WAAY,GAAM,SAAU,EAAM,EA6BnE,MAAsF,CACjG,IAAM,EAAO,EAAQ,EAErB,QAAS,EAAgB,GAAG,IAAoB,CAC9C,IAAM,EAAkB,EAAK,OAAS,EAAI,CAAE,GAAG,EAAsB,OAAQ,EAAK,EAAG,EAAI,EAEzF,OAAO,EAAK,cAAc,IAAI,YAAqB,OAAO,CAAK,EAAG,CAAe,CAAC,CACpF,EACF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vielzeug/ore",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Custom element authoring primitives — reactive templates, signals, slots, and automatic lifecycle management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -16,24 +16,6 @@
|
|
|
16
16
|
"import": "./dist/index.js",
|
|
17
17
|
"require": "./dist/index.cjs"
|
|
18
18
|
},
|
|
19
|
-
"./directives": {
|
|
20
|
-
"source": "./src/directives/index.ts",
|
|
21
|
-
"types": "./dist/directives/index.d.ts",
|
|
22
|
-
"import": "./dist/directives.js",
|
|
23
|
-
"require": "./dist/directives.cjs"
|
|
24
|
-
},
|
|
25
|
-
"./forms": {
|
|
26
|
-
"source": "./src/forms/index.ts",
|
|
27
|
-
"types": "./dist/forms/index.d.ts",
|
|
28
|
-
"import": "./dist/forms.js",
|
|
29
|
-
"require": "./dist/forms.cjs"
|
|
30
|
-
},
|
|
31
|
-
"./observers": {
|
|
32
|
-
"source": "./src/observers/index.ts",
|
|
33
|
-
"types": "./dist/observers/index.d.ts",
|
|
34
|
-
"import": "./dist/observers.js",
|
|
35
|
-
"require": "./dist/observers.cjs"
|
|
36
|
-
},
|
|
37
19
|
"./testing": {
|
|
38
20
|
"source": "./src/testing/index.ts",
|
|
39
21
|
"types": "./dist/testing/index.d.ts",
|
|
@@ -49,6 +31,7 @@
|
|
|
49
31
|
"prepublishOnly": "pnpm run build",
|
|
50
32
|
"preview": "vite preview",
|
|
51
33
|
"test": "vitest",
|
|
34
|
+
"test:types": "tsc -p tsconfig.json --noEmit",
|
|
52
35
|
"build:bundle": "vite build --config vite.bundle.config.ts"
|
|
53
36
|
},
|
|
54
37
|
"publishConfig": {
|
|
@@ -58,16 +41,23 @@
|
|
|
58
41
|
"engines": {
|
|
59
42
|
"node": ">=22"
|
|
60
43
|
},
|
|
61
|
-
"
|
|
62
|
-
"@vielzeug/assay": "
|
|
63
|
-
"@vielzeug/ripple": "
|
|
44
|
+
"peerDependencies": {
|
|
45
|
+
"@vielzeug/assay": "^2.0.0",
|
|
46
|
+
"@vielzeug/ripple": "^2.0.0"
|
|
47
|
+
},
|
|
48
|
+
"peerDependenciesMeta": {
|
|
49
|
+
"@vielzeug/assay": {
|
|
50
|
+
"optional": true
|
|
51
|
+
}
|
|
64
52
|
},
|
|
65
53
|
"devDependencies": {
|
|
66
|
-
"@types/node": "^26.1.
|
|
54
|
+
"@types/node": "^26.1.2",
|
|
55
|
+
"@vielzeug/assay": "2.0.0",
|
|
56
|
+
"@vielzeug/ripple": "2.0.0",
|
|
67
57
|
"axe-core": "^4.12.1",
|
|
68
|
-
"jsdom": "^
|
|
58
|
+
"jsdom": "^30.0.1",
|
|
69
59
|
"typescript": "^6.0.3",
|
|
70
|
-
"vite": "^8.
|
|
60
|
+
"vite": "^8.2.0",
|
|
71
61
|
"vitest": "^4.1.10"
|
|
72
62
|
}
|
|
73
63
|
}
|
package/dist/aria.cjs
DELETED
package/dist/aria.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"aria.cjs","names":[],"sources":["../src/aria.ts"],"sourcesContent":["/**\n * Reactive ARIA attribute sync.\n *\n * `aria()` is a thin convenience wrapper over `bind({ aria: config }, { target })` for the\n * common \"just ARIA, on one element\" case — normalizing bare ARIA property names\n * (`expanded` → `aria-expanded`) is `HostBindConfig.aria`'s job, not this function's; both\n * this and `bind()` share the exact same write path (`applyAttribute`/`setAttr`, including\n * its `on*`/dangerous-URL-scheme hardening), so there's nothing left to duplicate here.\n *\n * A component that needs both a regular attribute and ARIA attributes on the same element\n * can skip this wrapper entirely and pass `attr`/`aria` together in one `bind()` call —\n * one call, one cleanup function, instead of two.\n */\n\nimport { bind, type HostBindingValue } from './host-bind';\n\nexport type AriaConfig = Record<string, HostBindingValue>;\n\n/**\n * Reactively sync ARIA attributes on any element, auto-cleanup on component\n * disconnect. Returns a cleanup function that removes all reactive bindings.\n */\nexport const aria = (target: Element, config: AriaConfig): (() => void) => bind({ aria: config }, { target });\n"],"mappings":"mCAsBA,IAAa,GAAQ,EAAiB,IAAqC,EAAA,KAAK,CAAE,KAAM,CAAO,EAAG,CAAE,QAAO,CAAC"}
|
package/dist/aria.d.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Reactive ARIA attribute sync.
|
|
3
|
-
*
|
|
4
|
-
* `aria()` is a thin convenience wrapper over `bind({ aria: config }, { target })` for the
|
|
5
|
-
* common "just ARIA, on one element" case — normalizing bare ARIA property names
|
|
6
|
-
* (`expanded` → `aria-expanded`) is `HostBindConfig.aria`'s job, not this function's; both
|
|
7
|
-
* this and `bind()` share the exact same write path (`applyAttribute`/`setAttr`, including
|
|
8
|
-
* its `on*`/dangerous-URL-scheme hardening), so there's nothing left to duplicate here.
|
|
9
|
-
*
|
|
10
|
-
* A component that needs both a regular attribute and ARIA attributes on the same element
|
|
11
|
-
* can skip this wrapper entirely and pass `attr`/`aria` together in one `bind()` call —
|
|
12
|
-
* one call, one cleanup function, instead of two.
|
|
13
|
-
*/
|
|
14
|
-
import { type HostBindingValue } from './host-bind';
|
|
15
|
-
export type AriaConfig = Record<string, HostBindingValue>;
|
|
16
|
-
/**
|
|
17
|
-
* Reactively sync ARIA attributes on any element, auto-cleanup on component
|
|
18
|
-
* disconnect. Returns a cleanup function that removes all reactive bindings.
|
|
19
|
-
*/
|
|
20
|
-
export declare const aria: (target: Element, config: AriaConfig) => (() => void);
|
|
21
|
-
//# sourceMappingURL=aria.d.ts.map
|
package/dist/aria.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"aria.d.ts","sourceRoot":"","sources":["../src/aria.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAQ,KAAK,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE1D,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;AAE1D;;;GAGG;AACH,eAAO,MAAM,IAAI,GAAI,QAAQ,OAAO,EAAE,QAAQ,UAAU,KAAG,CAAC,MAAM,IAAI,CAAuC,CAAC"}
|
package/dist/aria.js
DELETED
package/dist/aria.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"aria.js","names":[],"sources":["../src/aria.ts"],"sourcesContent":["/**\n * Reactive ARIA attribute sync.\n *\n * `aria()` is a thin convenience wrapper over `bind({ aria: config }, { target })` for the\n * common \"just ARIA, on one element\" case — normalizing bare ARIA property names\n * (`expanded` → `aria-expanded`) is `HostBindConfig.aria`'s job, not this function's; both\n * this and `bind()` share the exact same write path (`applyAttribute`/`setAttr`, including\n * its `on*`/dangerous-URL-scheme hardening), so there's nothing left to duplicate here.\n *\n * A component that needs both a regular attribute and ARIA attributes on the same element\n * can skip this wrapper entirely and pass `attr`/`aria` together in one `bind()` call —\n * one call, one cleanup function, instead of two.\n */\n\nimport { bind, type HostBindingValue } from './host-bind';\n\nexport type AriaConfig = Record<string, HostBindingValue>;\n\n/**\n * Reactively sync ARIA attributes on any element, auto-cleanup on component\n * disconnect. Returns a cleanup function that removes all reactive bindings.\n */\nexport const aria = (target: Element, config: AriaConfig): (() => void) => bind({ aria: config }, { target });\n"],"mappings":"sCAsBA,IAAa,GAAQ,EAAiB,IAAqC,EAAK,CAAE,KAAM,CAAO,EAAG,CAAE,QAAO,CAAC"}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The niche/advanced directives — everyday ones (`each`, `when`, `classMap`, `styleMap`,
|
|
3
|
-
* `model`) live in the main `@vielzeug/ore` entry instead. `raw()` is security-sensitive
|
|
4
|
-
* (renders trusted HTML unescaped) and `live()` is form-control-specific, so both stay behind
|
|
5
|
-
* a deliberate, separate import.
|
|
6
|
-
*/
|
|
7
|
-
export { live, type LiveSignal } from './live';
|
|
8
|
-
export { raw, setRawSanitizer } from './raw';
|
|
9
|
-
/**
|
|
10
|
-
* Authoring API for custom directives — building blocks `each()`/`when()`/`raw()`/`model()`
|
|
11
|
-
* are themselves built on. Use `createDirectiveResult()` to write a directive that controls
|
|
12
|
-
* DOM insertion directly (an `html\`...${myDirective(...)}...\`` slot), or
|
|
13
|
-
* `createSpreadObject()` to write a `model()`-style helper that applies several bindings
|
|
14
|
-
* (value sync, event listeners) to one element from a single template expression.
|
|
15
|
-
*
|
|
16
|
-
* Both factories stamp a runtime brand — a hand-built object matching `DirectiveResult`'s or
|
|
17
|
-
* `SpreadObject`'s shape without going through these factories is *not* recognized by the
|
|
18
|
-
* template engine and silently renders as stringified text instead. Always construct through
|
|
19
|
-
* these functions, never build the object literal yourself.
|
|
20
|
-
*
|
|
21
|
-
* @example
|
|
22
|
-
* ```ts
|
|
23
|
-
* import { createDirectiveResult, type DirectiveResult } from '@vielzeug/ore/directives';
|
|
24
|
-
*
|
|
25
|
-
* function fadeIn(): DirectiveResult {
|
|
26
|
-
* return createDirectiveResult((anchor, registerCleanup) => {
|
|
27
|
-
* const el = document.createElement('div');
|
|
28
|
-
* el.textContent = 'Hello';
|
|
29
|
-
* anchor.parentNode?.insertBefore(el, anchor);
|
|
30
|
-
* registerCleanup(() => el.remove());
|
|
31
|
-
* });
|
|
32
|
-
* }
|
|
33
|
-
* ```
|
|
34
|
-
*/
|
|
35
|
-
export { createDirectiveResult, createSpreadObject, isDirectiveResult, isSpreadObject } from '../types/bindings';
|
|
36
|
-
export type { DirectiveResult, SpreadObject } from '../types/bindings';
|
|
37
|
-
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/directives/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,IAAI,EAAE,KAAK,UAAU,EAAE,MAAM,QAAQ,CAAC;AAC/C,OAAO,EAAE,GAAG,EAAE,eAAe,EAAE,MAAM,OAAO,CAAC;AAE7C;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACjH,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
const e=require("../types/bindings.cjs"),t=require("../utils/dom.cjs");let n=require("@vielzeug/ripple");function r(r){return e.createSpreadObject((e,i)=>{let a=e,o=a.type===`checkbox`,s=a.type===`number`||a.type===`range`,c=e instanceof HTMLSelectElement,l=c&&e.multiple,u=(0,n.effect)(()=>{let t=r.value;if(l){let n=Array.isArray(t)?t:[],r=e;for(let e of r.options)e.selected=n.includes(e.value)}else o?a.checked=!!t:e.value=t==null?``:String(t)});i(()=>u.dispose()),i(t.listen(e,c?`change`:`input`,e=>{let t=e.target;if(l){let t=e.target;r.value=Array.from(t.selectedOptions).map(e=>e.value)}else o?r.value=t.checked:s?r.value=t.value===``?0:Number(t.value):r.value=t.value}))})}exports.model=r;
|
|
2
|
-
//# sourceMappingURL=model.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"model.cjs","names":[],"sources":["../../src/directives/model.ts"],"sourcesContent":["import { effect as rawEffect, type Signal } from '@vielzeug/ripple';\n\nimport { createSpreadObject, type SpreadObject } from '../types/bindings';\nimport { listen } from '../utils/dom';\n\n/**\n * Two-way binding spread for form inputs.\n * Syncs the signal value to the element's DOM value and back.\n *\n * Supports `type=\"text\"` (default), `type=\"number\"`, `type=\"range\"`,\n * `type=\"checkbox\"`, `<select>` (single-select), and\n * `<select multiple>` (multi-select, `Signal<string[]>`).\n *\n * @example\n * ```ts\n * const name = signal('');\n * html`<input type=\"text\" ${model(name)} />`\n *\n * const count = signal(0);\n * html`<input type=\"number\" ${model(count)} />`\n *\n * const checked = signal(false);\n * html`<input type=\"checkbox\" ${model(checked)} />`\n *\n * const selected = signal<string[]>([]);\n * html`<select multiple ${model(selected)}><option value=\"a\">A</option></select>`\n * ```\n */\nexport function model<T extends string | number | boolean | null>(source: Signal<T>): SpreadObject;\nexport function model(source: Signal<string[]>): SpreadObject;\nexport function model<T extends string | number | boolean | null | string[]>(source: Signal<T>): SpreadObject {\n return createSpreadObject((el, registerCleanup) => {\n const input = el as HTMLInputElement;\n const isCheckbox = input.type === 'checkbox';\n const isNumeric = input.type === 'number' || input.type === 'range';\n const isSelect = el instanceof HTMLSelectElement;\n const isMultiSelect = isSelect && (el as HTMLSelectElement).multiple;\n\n // Signal → DOM\n const sub = rawEffect(() => {\n const v = source.value;\n\n if (isMultiSelect) {\n const selected = Array.isArray(v) ? (v as string[]) : [];\n const selectEl = el as HTMLSelectElement;\n\n for (const opt of selectEl.options) {\n opt.selected = selected.includes(opt.value);\n }\n } else if (isCheckbox) {\n input.checked = Boolean(v);\n } else {\n (el as HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement).value =\n v == null ? '' : String(v as string | number | boolean | null);\n }\n });\n\n registerCleanup(() => sub.dispose());\n\n // DOM → Signal\n // <select> fires 'change'; text/number/range/textarea/checkbox fire 'input'.\n const eventName = isSelect ? 'change' : 'input';\n\n registerCleanup(\n listen(el, eventName, (e: Event) => {\n const target = e.target as HTMLInputElement;\n\n if (isMultiSelect) {\n const selectEl = e.target as HTMLSelectElement;\n const values = Array.from(selectEl.selectedOptions).map((opt) => opt.value);\n\n (source as Signal<string[]>).value = values;\n } else if (isCheckbox) {\n source.value = target.checked as T;\n } else if (isNumeric) {\n source.value = (target.value === '' ? 0 : Number(target.value)) as T;\n } else {\n source.value = target.value as T;\n }\n }),\n );\n });\n}\n"],"mappings":"yGA8BA,SAAgB,EAA6D,EAAiC,CAC5G,OAAO,EAAA,oBAAoB,EAAI,IAAoB,CACjD,IAAM,EAAQ,EACR,EAAa,EAAM,OAAS,WAC5B,EAAY,EAAM,OAAS,UAAY,EAAM,OAAS,QACtD,EAAW,aAAc,kBACzB,EAAgB,GAAa,EAAyB,SAGtD,GAAA,EAAA,EAAA,OAAA,KAAsB,CAC1B,IAAM,EAAI,EAAO,MAEjB,GAAI,EAAe,CACjB,IAAM,EAAW,MAAM,QAAQ,CAAC,EAAK,EAAiB,CAAC,EACjD,EAAW,EAEjB,IAAK,IAAM,KAAO,EAAS,QACzB,EAAI,SAAW,EAAS,SAAS,EAAI,KAAK,CAE9C,MAAW,EACT,EAAM,QAAU,EAAQ,EAExB,EAAmE,MACjE,GAAK,KAAO,GAAK,OAAO,CAAqC,CAEnE,CAAC,EAED,MAAsB,EAAI,QAAQ,CAAC,EAMnC,EACE,EAAA,OAAO,EAHS,EAAW,SAAW,QAGf,GAAa,CAClC,IAAM,EAAS,EAAE,OAEjB,GAAI,EAAe,CACjB,IAAM,EAAW,EAAE,OAGnB,EAA6B,MAFd,MAAM,KAAK,EAAS,eAAe,CAAC,CAAC,IAAK,GAAQ,EAAI,KAEhC,CACvC,MAAW,EACT,EAAO,MAAQ,EAAO,QACb,EACT,EAAO,MAAS,EAAO,QAAU,GAAK,EAAI,OAAO,EAAO,KAAK,EAE7D,EAAO,MAAQ,EAAO,KAE1B,CAAC,CACH,CACF,CAAC,CACH"}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { type Signal } from '@vielzeug/ripple';
|
|
2
|
-
import { type SpreadObject } from '../types/bindings';
|
|
3
|
-
/**
|
|
4
|
-
* Two-way binding spread for form inputs.
|
|
5
|
-
* Syncs the signal value to the element's DOM value and back.
|
|
6
|
-
*
|
|
7
|
-
* Supports `type="text"` (default), `type="number"`, `type="range"`,
|
|
8
|
-
* `type="checkbox"`, `<select>` (single-select), and
|
|
9
|
-
* `<select multiple>` (multi-select, `Signal<string[]>`).
|
|
10
|
-
*
|
|
11
|
-
* @example
|
|
12
|
-
* ```ts
|
|
13
|
-
* const name = signal('');
|
|
14
|
-
* html`<input type="text" ${model(name)} />`
|
|
15
|
-
*
|
|
16
|
-
* const count = signal(0);
|
|
17
|
-
* html`<input type="number" ${model(count)} />`
|
|
18
|
-
*
|
|
19
|
-
* const checked = signal(false);
|
|
20
|
-
* html`<input type="checkbox" ${model(checked)} />`
|
|
21
|
-
*
|
|
22
|
-
* const selected = signal<string[]>([]);
|
|
23
|
-
* html`<select multiple ${model(selected)}><option value="a">A</option></select>`
|
|
24
|
-
* ```
|
|
25
|
-
*/
|
|
26
|
-
export declare function model<T extends string | number | boolean | null>(source: Signal<T>): SpreadObject;
|
|
27
|
-
export declare function model(source: Signal<string[]>): SpreadObject;
|
|
28
|
-
//# sourceMappingURL=model.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../src/directives/model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAEpE,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAG1E;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,KAAK,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC;AACnG,wBAAgB,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,YAAY,CAAC"}
|
package/dist/directives/model.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{createSpreadObject as e}from"../types/bindings.js";import{listen as t}from"../utils/dom.js";import{effect as n}from"@vielzeug/ripple";function r(r){return e((e,i)=>{let a=e,o=a.type===`checkbox`,s=a.type===`number`||a.type===`range`,c=e instanceof HTMLSelectElement,l=c&&e.multiple,u=n(()=>{let t=r.value;if(l){let n=Array.isArray(t)?t:[],r=e;for(let e of r.options)e.selected=n.includes(e.value)}else o?a.checked=!!t:e.value=t==null?``:String(t)});i(()=>u.dispose()),i(t(e,c?`change`:`input`,e=>{let t=e.target;if(l){let t=e.target;r.value=Array.from(t.selectedOptions).map(e=>e.value)}else o?r.value=t.checked:s?r.value=t.value===``?0:Number(t.value):r.value=t.value}))})}export{r as model};
|
|
2
|
-
//# sourceMappingURL=model.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"model.js","names":[],"sources":["../../src/directives/model.ts"],"sourcesContent":["import { effect as rawEffect, type Signal } from '@vielzeug/ripple';\n\nimport { createSpreadObject, type SpreadObject } from '../types/bindings';\nimport { listen } from '../utils/dom';\n\n/**\n * Two-way binding spread for form inputs.\n * Syncs the signal value to the element's DOM value and back.\n *\n * Supports `type=\"text\"` (default), `type=\"number\"`, `type=\"range\"`,\n * `type=\"checkbox\"`, `<select>` (single-select), and\n * `<select multiple>` (multi-select, `Signal<string[]>`).\n *\n * @example\n * ```ts\n * const name = signal('');\n * html`<input type=\"text\" ${model(name)} />`\n *\n * const count = signal(0);\n * html`<input type=\"number\" ${model(count)} />`\n *\n * const checked = signal(false);\n * html`<input type=\"checkbox\" ${model(checked)} />`\n *\n * const selected = signal<string[]>([]);\n * html`<select multiple ${model(selected)}><option value=\"a\">A</option></select>`\n * ```\n */\nexport function model<T extends string | number | boolean | null>(source: Signal<T>): SpreadObject;\nexport function model(source: Signal<string[]>): SpreadObject;\nexport function model<T extends string | number | boolean | null | string[]>(source: Signal<T>): SpreadObject {\n return createSpreadObject((el, registerCleanup) => {\n const input = el as HTMLInputElement;\n const isCheckbox = input.type === 'checkbox';\n const isNumeric = input.type === 'number' || input.type === 'range';\n const isSelect = el instanceof HTMLSelectElement;\n const isMultiSelect = isSelect && (el as HTMLSelectElement).multiple;\n\n // Signal → DOM\n const sub = rawEffect(() => {\n const v = source.value;\n\n if (isMultiSelect) {\n const selected = Array.isArray(v) ? (v as string[]) : [];\n const selectEl = el as HTMLSelectElement;\n\n for (const opt of selectEl.options) {\n opt.selected = selected.includes(opt.value);\n }\n } else if (isCheckbox) {\n input.checked = Boolean(v);\n } else {\n (el as HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement).value =\n v == null ? '' : String(v as string | number | boolean | null);\n }\n });\n\n registerCleanup(() => sub.dispose());\n\n // DOM → Signal\n // <select> fires 'change'; text/number/range/textarea/checkbox fire 'input'.\n const eventName = isSelect ? 'change' : 'input';\n\n registerCleanup(\n listen(el, eventName, (e: Event) => {\n const target = e.target as HTMLInputElement;\n\n if (isMultiSelect) {\n const selectEl = e.target as HTMLSelectElement;\n const values = Array.from(selectEl.selectedOptions).map((opt) => opt.value);\n\n (source as Signal<string[]>).value = values;\n } else if (isCheckbox) {\n source.value = target.checked as T;\n } else if (isNumeric) {\n source.value = (target.value === '' ? 0 : Number(target.value)) as T;\n } else {\n source.value = target.value as T;\n }\n }),\n );\n });\n}\n"],"mappings":"6IA8BA,SAAgB,EAA6D,EAAiC,CAC5G,OAAO,GAAoB,EAAI,IAAoB,CACjD,IAAM,EAAQ,EACR,EAAa,EAAM,OAAS,WAC5B,EAAY,EAAM,OAAS,UAAY,EAAM,OAAS,QACtD,EAAW,aAAc,kBACzB,EAAgB,GAAa,EAAyB,SAGtD,EAAM,MAAgB,CAC1B,IAAM,EAAI,EAAO,MAEjB,GAAI,EAAe,CACjB,IAAM,EAAW,MAAM,QAAQ,CAAC,EAAK,EAAiB,CAAC,EACjD,EAAW,EAEjB,IAAK,IAAM,KAAO,EAAS,QACzB,EAAI,SAAW,EAAS,SAAS,EAAI,KAAK,CAE9C,MAAW,EACT,EAAM,QAAU,EAAQ,EAExB,EAAmE,MACjE,GAAK,KAAO,GAAK,OAAO,CAAqC,CAEnE,CAAC,EAED,MAAsB,EAAI,QAAQ,CAAC,EAMnC,EACE,EAAO,EAHS,EAAW,SAAW,QAGf,GAAa,CAClC,IAAM,EAAS,EAAE,OAEjB,GAAI,EAAe,CACjB,IAAM,EAAW,EAAE,OAGnB,EAA6B,MAFd,MAAM,KAAK,EAAS,eAAe,CAAC,CAAC,IAAK,GAAQ,EAAI,KAEhC,CACvC,MAAW,EACT,EAAO,MAAQ,EAAO,QACb,EACT,EAAO,MAAS,EAAO,QAAU,GAAK,EAAI,OAAO,EAAO,KAAK,EAE7D,EAAO,MAAQ,EAAO,KAE1B,CAAC,CACH,CACF,CAAC,CACH"}
|
package/dist/directives/raw.cjs
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
const e=require("../_dev.cjs"),t=require("../errors.cjs"),n=require("../types/bindings.cjs"),r=require("../utils/dom.cjs");let i=require("@vielzeug/ripple");var a=null,o=!1,s=e=>{a=e,e||(o=!1)},c=()=>{a=null,o=!1},l=t=>a?a(t):(t&&!o&&(o=!0,e.warn(`raw() was called without a sanitizer registered. Passing user-supplied HTML directly to raw() is an XSS risk. Register a sanitizer with setRawSanitizer() — e.g. setRawSanitizer(DOMPURIFY.sanitize).`)),t),u=(e,t,n)=>{let r=document.createElement(`template`);r.innerHTML=e;let i=Array.from(r.content.cloneNode(!0).childNodes);for(let e of i)t.insertBefore(e,n);return i};function d(e){if(typeof e==`function`){let t=(0,i.computed)(e);return n.createDirectiveResult((e,n)=>{n(()=>t.dispose()),d(t).mount(e,n)})}return n.createDirectiveResult((n,a)=>{let o=n.parentNode;t.invariant(o,`raw() anchor comment has no parent node`);let s=document.createComment(`raw/end`);if(o.insertBefore(s,n.nextSibling),(0,i.isReactive)(e)){let t=r.createReplaceableSlot(),n=e,c=(0,i.effect)(()=>{t.clear(),t.setNodes(u(l(n.value),o,s))});a(()=>c.dispose()),a(()=>{t.clear(),s.remove()})}else u(l(e),o,s),a(()=>s.remove())})}exports._resetRawSanitizer=c,exports.raw=d,exports.setRawSanitizer=s;
|
|
2
|
-
//# sourceMappingURL=raw.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"raw.cjs","names":[],"sources":["../../src/directives/raw.ts"],"sourcesContent":["import { computed, effect as rawEffect, isReactive, type Readable, type Signal } from '@vielzeug/ripple';\n\nimport { warn } from '../_dev';\nimport { invariant } from '../errors';\nimport { createDirectiveResult, type DirectiveResult } from '../types/bindings';\nimport { createReplaceableSlot } from '../utils/dom';\n\ntype RawSanitizer = (html: string) => string;\n\nlet _sanitizer: RawSanitizer | null = null;\nlet _warned = false;\n\nexport const setRawSanitizer = (fn: RawSanitizer | null): void => {\n _sanitizer = fn;\n\n if (!fn) _warned = false;\n};\n\n/** @internal */\nexport const _resetRawSanitizer = (): void => {\n _sanitizer = null;\n _warned = false;\n};\n\nconst sanitize = (value: string): string => {\n if (_sanitizer) return _sanitizer(value);\n\n if (value && !_warned) {\n _warned = true;\n warn(\n 'raw() was called without a sanitizer registered. ' +\n 'Passing user-supplied HTML directly to raw() is an XSS risk. ' +\n 'Register a sanitizer with setRawSanitizer() — e.g. setRawSanitizer(DOMPURIFY.sanitize).',\n );\n }\n\n return value;\n};\n\nconst parseRaw = (html: string, parent: ParentNode, insertBefore: Node): Node[] => {\n const tpl = document.createElement('template');\n\n tpl.innerHTML = html;\n\n const nodes = Array.from(tpl.content.cloneNode(true).childNodes);\n\n for (const node of nodes) parent.insertBefore(node, insertBefore);\n\n return nodes;\n};\n\n/**\n * Renders a trusted HTML string without escaping as a DirectiveResult.\n * Only use with content you control — passing user-supplied strings\n * directly is an XSS risk. Register a sanitizer with setRawSanitizer()\n * to add a runtime safety net.\n *\n * Supports static strings, signals, and getter functions `() => string`.\n * When reactive, the DOM is updated in-place whenever the value changes.\n */\nexport function raw(value: (() => string) | string | Signal<string> | Readable<string>): DirectiveResult {\n if (typeof value === 'function') {\n const c = computed(value);\n\n return createDirectiveResult((anchor, registerCleanup) => {\n registerCleanup(() => c.dispose());\n raw(c).mount(anchor, registerCleanup);\n });\n }\n\n return createDirectiveResult((anchor, registerCleanup) => {\n const parent = anchor.parentNode;\n\n invariant(parent, 'raw() anchor comment has no parent node');\n\n const endMarker = document.createComment('raw/end');\n\n parent.insertBefore(endMarker, anchor.nextSibling);\n\n if (isReactive(value)) {\n const slot = createReplaceableSlot();\n const src = value as Readable<string>;\n\n const stop = rawEffect(() => {\n slot.clear();\n slot.setNodes(parseRaw(sanitize(src.value), parent, endMarker));\n });\n\n registerCleanup(() => stop.dispose());\n registerCleanup(() => {\n slot.clear();\n endMarker.remove();\n });\n } else {\n parseRaw(sanitize(value), parent, endMarker);\n\n registerCleanup(() => endMarker.remove());\n }\n });\n}\n"],"mappings":"6JASA,IAAI,EAAkC,KAClC,EAAU,GAED,EAAmB,GAAkC,CAChE,EAAa,EAER,IAAI,EAAU,GACrB,EAGa,MAAiC,CAC5C,EAAa,KACb,EAAU,EACZ,EAEM,EAAY,GACZ,EAAmB,EAAW,CAAK,GAEnC,GAAS,CAAC,IACZ,EAAU,GACV,EAAA,KACE,uMAGF,GAGK,GAGH,GAAY,EAAc,EAAoB,IAA+B,CACjF,IAAM,EAAM,SAAS,cAAc,UAAU,EAE7C,EAAI,UAAY,EAEhB,IAAM,EAAQ,MAAM,KAAK,EAAI,QAAQ,UAAU,EAAI,CAAC,CAAC,UAAU,EAE/D,IAAK,IAAM,KAAQ,EAAO,EAAO,aAAa,EAAM,CAAY,EAEhE,OAAO,CACT,EAWA,SAAgB,EAAI,EAAqF,CACvG,GAAI,OAAO,GAAU,WAAY,CAC/B,IAAM,GAAA,EAAA,EAAA,SAAA,CAAa,CAAK,EAExB,OAAO,EAAA,uBAAuB,EAAQ,IAAoB,CACxD,MAAsB,EAAE,QAAQ,CAAC,EACjC,EAAI,CAAC,CAAC,CAAC,MAAM,EAAQ,CAAe,CACtC,CAAC,CACH,CAEA,OAAO,EAAA,uBAAuB,EAAQ,IAAoB,CACxD,IAAM,EAAS,EAAO,WAEtB,EAAA,UAAU,EAAQ,yCAAyC,EAE3D,IAAM,EAAY,SAAS,cAAc,SAAS,EAIlD,GAFA,EAAO,aAAa,EAAW,EAAO,WAAW,GAEjD,EAAA,EAAA,WAAA,CAAe,CAAK,EAAG,CACrB,IAAM,EAAO,EAAA,sBAAsB,EAC7B,EAAM,EAEN,GAAA,EAAA,EAAA,OAAA,KAAuB,CAC3B,EAAK,MAAM,EACX,EAAK,SAAS,EAAS,EAAS,EAAI,KAAK,EAAG,EAAQ,CAAS,CAAC,CAChE,CAAC,EAED,MAAsB,EAAK,QAAQ,CAAC,EACpC,MAAsB,CACpB,EAAK,MAAM,EACX,EAAU,OAAO,CACnB,CAAC,CACH,MACE,EAAS,EAAS,CAAK,EAAG,EAAQ,CAAS,EAE3C,MAAsB,EAAU,OAAO,CAAC,CAE5C,CAAC,CACH"}
|
package/dist/directives/raw.d.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { type Readable, type Signal } from '@vielzeug/ripple';
|
|
2
|
-
import { type DirectiveResult } from '../types/bindings';
|
|
3
|
-
type RawSanitizer = (html: string) => string;
|
|
4
|
-
export declare const setRawSanitizer: (fn: RawSanitizer | null) => void;
|
|
5
|
-
/**
|
|
6
|
-
* Renders a trusted HTML string without escaping as a DirectiveResult.
|
|
7
|
-
* Only use with content you control — passing user-supplied strings
|
|
8
|
-
* directly is an XSS risk. Register a sanitizer with setRawSanitizer()
|
|
9
|
-
* to add a runtime safety net.
|
|
10
|
-
*
|
|
11
|
-
* Supports static strings, signals, and getter functions `() => string`.
|
|
12
|
-
* When reactive, the DOM is updated in-place whenever the value changes.
|
|
13
|
-
*/
|
|
14
|
-
export declare function raw(value: (() => string) | string | Signal<string> | Readable<string>): DirectiveResult;
|
|
15
|
-
export {};
|
|
16
|
-
//# sourceMappingURL=raw.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"raw.d.ts","sourceRoot":"","sources":["../../src/directives/raw.ts"],"names":[],"mappings":"AAAA,OAAO,EAA6C,KAAK,QAAQ,EAAE,KAAK,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAIzG,OAAO,EAAyB,KAAK,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAGhF,KAAK,YAAY,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;AAK7C,eAAO,MAAM,eAAe,GAAI,IAAI,YAAY,GAAG,IAAI,KAAG,IAIzD,CAAC;AAmCF;;;;;;;;GAQG;AACH,wBAAgB,GAAG,CAAC,KAAK,EAAE,CAAC,MAAM,MAAM,CAAC,GAAG,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC,GAAG,eAAe,CAuCvG"}
|
package/dist/directives/raw.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{warn as e}from"../_dev.js";import{invariant as t}from"../errors.js";import{createDirectiveResult as n}from"../types/bindings.js";import{createReplaceableSlot as r}from"../utils/dom.js";import{computed as i,effect as a,isReactive as o}from"@vielzeug/ripple";var s=null,c=!1,l=e=>{s=e,e||(c=!1)},u=()=>{s=null,c=!1},d=t=>s?s(t):(t&&!c&&(c=!0,e(`raw() was called without a sanitizer registered. Passing user-supplied HTML directly to raw() is an XSS risk. Register a sanitizer with setRawSanitizer() — e.g. setRawSanitizer(DOMPURIFY.sanitize).`)),t),f=(e,t,n)=>{let r=document.createElement(`template`);r.innerHTML=e;let i=Array.from(r.content.cloneNode(!0).childNodes);for(let e of i)t.insertBefore(e,n);return i};function p(e){if(typeof e==`function`){let t=i(e);return n((e,n)=>{n(()=>t.dispose()),p(t).mount(e,n)})}return n((n,i)=>{let s=n.parentNode;t(s,`raw() anchor comment has no parent node`);let c=document.createComment(`raw/end`);if(s.insertBefore(c,n.nextSibling),o(e)){let t=r(),n=e,o=a(()=>{t.clear(),t.setNodes(f(d(n.value),s,c))});i(()=>o.dispose()),i(()=>{t.clear(),c.remove()})}else f(d(e),s,c),i(()=>c.remove())})}export{u as _resetRawSanitizer,p as raw,l as setRawSanitizer};
|
|
2
|
-
//# sourceMappingURL=raw.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"raw.js","names":[],"sources":["../../src/directives/raw.ts"],"sourcesContent":["import { computed, effect as rawEffect, isReactive, type Readable, type Signal } from '@vielzeug/ripple';\n\nimport { warn } from '../_dev';\nimport { invariant } from '../errors';\nimport { createDirectiveResult, type DirectiveResult } from '../types/bindings';\nimport { createReplaceableSlot } from '../utils/dom';\n\ntype RawSanitizer = (html: string) => string;\n\nlet _sanitizer: RawSanitizer | null = null;\nlet _warned = false;\n\nexport const setRawSanitizer = (fn: RawSanitizer | null): void => {\n _sanitizer = fn;\n\n if (!fn) _warned = false;\n};\n\n/** @internal */\nexport const _resetRawSanitizer = (): void => {\n _sanitizer = null;\n _warned = false;\n};\n\nconst sanitize = (value: string): string => {\n if (_sanitizer) return _sanitizer(value);\n\n if (value && !_warned) {\n _warned = true;\n warn(\n 'raw() was called without a sanitizer registered. ' +\n 'Passing user-supplied HTML directly to raw() is an XSS risk. ' +\n 'Register a sanitizer with setRawSanitizer() — e.g. setRawSanitizer(DOMPURIFY.sanitize).',\n );\n }\n\n return value;\n};\n\nconst parseRaw = (html: string, parent: ParentNode, insertBefore: Node): Node[] => {\n const tpl = document.createElement('template');\n\n tpl.innerHTML = html;\n\n const nodes = Array.from(tpl.content.cloneNode(true).childNodes);\n\n for (const node of nodes) parent.insertBefore(node, insertBefore);\n\n return nodes;\n};\n\n/**\n * Renders a trusted HTML string without escaping as a DirectiveResult.\n * Only use with content you control — passing user-supplied strings\n * directly is an XSS risk. Register a sanitizer with setRawSanitizer()\n * to add a runtime safety net.\n *\n * Supports static strings, signals, and getter functions `() => string`.\n * When reactive, the DOM is updated in-place whenever the value changes.\n */\nexport function raw(value: (() => string) | string | Signal<string> | Readable<string>): DirectiveResult {\n if (typeof value === 'function') {\n const c = computed(value);\n\n return createDirectiveResult((anchor, registerCleanup) => {\n registerCleanup(() => c.dispose());\n raw(c).mount(anchor, registerCleanup);\n });\n }\n\n return createDirectiveResult((anchor, registerCleanup) => {\n const parent = anchor.parentNode;\n\n invariant(parent, 'raw() anchor comment has no parent node');\n\n const endMarker = document.createComment('raw/end');\n\n parent.insertBefore(endMarker, anchor.nextSibling);\n\n if (isReactive(value)) {\n const slot = createReplaceableSlot();\n const src = value as Readable<string>;\n\n const stop = rawEffect(() => {\n slot.clear();\n slot.setNodes(parseRaw(sanitize(src.value), parent, endMarker));\n });\n\n registerCleanup(() => stop.dispose());\n registerCleanup(() => {\n slot.clear();\n endMarker.remove();\n });\n } else {\n parseRaw(sanitize(value), parent, endMarker);\n\n registerCleanup(() => endMarker.remove());\n }\n });\n}\n"],"mappings":"wQASA,IAAI,EAAkC,KAClC,EAAU,GAED,EAAmB,GAAkC,CAChE,EAAa,EAER,IAAI,EAAU,GACrB,EAGa,MAAiC,CAC5C,EAAa,KACb,EAAU,EACZ,EAEM,EAAY,GACZ,EAAmB,EAAW,CAAK,GAEnC,GAAS,CAAC,IACZ,EAAU,GACV,EACE,uMAGF,GAGK,GAGH,GAAY,EAAc,EAAoB,IAA+B,CACjF,IAAM,EAAM,SAAS,cAAc,UAAU,EAE7C,EAAI,UAAY,EAEhB,IAAM,EAAQ,MAAM,KAAK,EAAI,QAAQ,UAAU,EAAI,CAAC,CAAC,UAAU,EAE/D,IAAK,IAAM,KAAQ,EAAO,EAAO,aAAa,EAAM,CAAY,EAEhE,OAAO,CACT,EAWA,SAAgB,EAAI,EAAqF,CACvG,GAAI,OAAO,GAAU,WAAY,CAC/B,IAAM,EAAI,EAAS,CAAK,EAExB,OAAO,GAAuB,EAAQ,IAAoB,CACxD,MAAsB,EAAE,QAAQ,CAAC,EACjC,EAAI,CAAC,CAAC,CAAC,MAAM,EAAQ,CAAe,CACtC,CAAC,CACH,CAEA,OAAO,GAAuB,EAAQ,IAAoB,CACxD,IAAM,EAAS,EAAO,WAEtB,EAAU,EAAQ,yCAAyC,EAE3D,IAAM,EAAY,SAAS,cAAc,SAAS,EAIlD,GAFA,EAAO,aAAa,EAAW,EAAO,WAAW,EAE7C,EAAW,CAAK,EAAG,CACrB,IAAM,EAAO,EAAsB,EAC7B,EAAM,EAEN,EAAO,MAAgB,CAC3B,EAAK,MAAM,EACX,EAAK,SAAS,EAAS,EAAS,EAAI,KAAK,EAAG,EAAQ,CAAS,CAAC,CAChE,CAAC,EAED,MAAsB,EAAK,QAAQ,CAAC,EACpC,MAAsB,CACpB,EAAK,MAAM,EACX,EAAU,OAAO,CACnB,CAAC,CACH,MACE,EAAS,EAAS,CAAK,EAAG,EAAQ,CAAS,EAE3C,MAAsB,EAAU,OAAO,CAAC,CAE5C,CAAC,CACH"}
|
package/dist/directives.cjs
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./directives/live.cjs"),t=require("./types/bindings.cjs"),n=require("./directives/raw.cjs");exports.createDirectiveResult=t.createDirectiveResult,exports.createSpreadObject=t.createSpreadObject,exports.isDirectiveResult=t.isDirectiveResult,exports.isSpreadObject=t.isSpreadObject,exports.live=e.live,exports.raw=n.raw,exports.setRawSanitizer=n.setRawSanitizer;
|
package/dist/directives.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{live as e}from"./directives/live.js";import{createDirectiveResult as t,createSpreadObject as n,isDirectiveResult as r,isSpreadObject as i}from"./types/bindings.js";import{raw as a,setRawSanitizer as o}from"./directives/raw.js";export{t as createDirectiveResult,n as createSpreadObject,r as isDirectiveResult,i as isSpreadObject,e as live,a as raw,o as setRawSanitizer};
|
package/dist/forms/context.cjs
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
const e=require("../context.cjs");let t=require("@vielzeug/ripple");var n=e.createContext(`ore:form-context`);function r(e={}){let n=(0,t.signal)([]),r=(0,t.signal)(!1),i=(0,t.signal)(!1),a=(0,t.signal)(null);return{clearStatus:()=>{i.value=!1,a.value=null,e.onReset?.()},dirty:i,error:a,markDirty:()=>{i.value=!0},registerField:e=>(n.value=[...n.value,e],()=>{n.value=n.value.filter(t=>t!==e)}),submit:async t=>{if(t?.preventDefault(),!r.value){r.value=!0,a.value=null;try{await e.onSubmit?.(t),i.value=!1}catch(e){a.value=e}finally{r.value=!1}}},submitting:r,valid:(0,t.computed)(()=>n.value.every(e=>e.value))}}exports.FORM_CONTEXT_KEY=n,exports.createFormContext=r;
|
|
2
|
-
//# sourceMappingURL=context.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"context.cjs","names":[],"sources":["../../src/forms/context.ts"],"sourcesContent":["import { computed, type Readable, signal } from '@vielzeug/ripple';\n\nimport { createContext } from '../context';\n\n/**\n * Context shape injected by child field components.\n * Contains only what a field needs — not submit/error/status APIs.\n */\nexport type FormFieldContext = {\n /** Whether any field has been touched (interacted with). Set via markDirty(). */\n readonly dirty: Readable<boolean>;\n markDirty(): void;\n /**\n * Register a field's validity signal with the form context.\n * Returns a cleanup function.\n */\n registerField(validity: Readable<boolean>): () => void;\n};\n\n/**\n * Full form controller returned by `createFormContext`.\n * Extends `FormFieldContext` with submission and status APIs.\n */\nexport type FormController = FormFieldContext & {\n /**\n * Clear `dirty` and `error` status signals and invoke `onReset` if provided.\n * Note: this does not reset individual field values — pass an `onReset` callback\n * to handle value restoration.\n */\n clearStatus(): void;\n /** The last submit error, or null if the last submit succeeded. */\n readonly error: Readable<unknown>;\n /** Submit the form programmatically. */\n submit(e?: Event): Promise<void>;\n /** Whether the form is currently submitting. */\n readonly submitting: Readable<boolean>;\n /** Whether all fields in the form are valid. */\n readonly valid: Readable<boolean>;\n};\n\nexport const FORM_CONTEXT_KEY = createContext<FormFieldContext>('ore:form-context');\n\n/**\n * Create a `FormController` for coordinating form state across child field components.\n * Call `provide(FORM_CONTEXT_KEY, form)` to make it available to descendants.\n *\n * @example\n * ```ts\n * define('my-form', {\n * setup(_props) {\n * const form = createFormContext({ onSubmit: async (e) => { ... } });\n * provide(FORM_CONTEXT_KEY, form);\n * return html`<form @submit=${form.submit}><slot></slot></form>`;\n * }\n * });\n * ```\n */\nexport function createFormContext(\n options: {\n onReset?: () => void;\n onSubmit?: (e?: Event) => void | Promise<void>;\n } = {},\n): FormController {\n const fieldValiditySignals = signal<Array<Readable<boolean>>>([]);\n const submitting = signal(false);\n const dirty = signal(false);\n const error = signal<unknown>(null);\n\n // Note: [].every() is vacuously true, so valid is true when no fields are registered.\n // This is intentional — a form with no fields is considered valid (nothing to invalidate it).\n const valid = computed(() => fieldValiditySignals.value.every((s) => s.value));\n\n const submit = async (e?: Event): Promise<void> => {\n e?.preventDefault();\n\n if (submitting.value) return;\n\n submitting.value = true;\n error.value = null;\n\n try {\n await options.onSubmit?.(e);\n dirty.value = false;\n } catch (err) {\n error.value = err;\n } finally {\n submitting.value = false;\n }\n };\n\n const clearStatus = (): void => {\n dirty.value = false;\n error.value = null;\n options.onReset?.();\n };\n\n const markDirty = (): void => {\n dirty.value = true;\n };\n\n const registerField = (validity: Readable<boolean>): (() => void) => {\n fieldValiditySignals.value = [...fieldValiditySignals.value, validity];\n\n return () => {\n fieldValiditySignals.value = fieldValiditySignals.value.filter((s) => s !== validity);\n };\n };\n\n return { clearStatus, dirty, error, markDirty, registerField, submit, submitting, valid };\n}\n"],"mappings":"oEAwCA,IAAa,EAAmB,EAAA,cAAgC,kBAAkB,EAiBlF,SAAgB,EACd,EAGI,CAAC,EACW,CAChB,IAAM,GAAA,EAAA,EAAA,OAAA,CAAwD,CAAC,CAAC,EAC1D,GAAA,EAAA,EAAA,OAAA,CAAoB,EAAK,EACzB,GAAA,EAAA,EAAA,OAAA,CAAe,EAAK,EACpB,GAAA,EAAA,EAAA,OAAA,CAAwB,IAAI,EA0ClC,MAAO,CAAE,gBAlBuB,CAC9B,EAAM,MAAQ,GACd,EAAM,MAAQ,KACd,EAAQ,UAAU,CACpB,EAcsB,QAAO,QAAO,cAZN,CAC5B,EAAM,MAAQ,EAChB,EAU+C,cARxB,IACrB,EAAqB,MAAQ,CAAC,GAAG,EAAqB,MAAO,CAAQ,MAExD,CACX,EAAqB,MAAQ,EAAqB,MAAM,OAAQ,GAAM,IAAM,CAAQ,CACtF,GAG4D,YApCxC,IAA6B,CACjD,MAAG,eAAe,EAEd,GAAW,MAGf,CADA,EAAW,MAAQ,GACnB,EAAM,MAAQ,KAEd,GAAI,CACF,MAAM,EAAQ,WAAW,CAAC,EAC1B,EAAM,MAAQ,EAChB,OAAS,EAAK,CACZ,EAAM,MAAQ,CAChB,QAAU,CACR,EAAW,MAAQ,EACrB,CATc,CAUhB,EAoBsE,aAAY,OAtC5E,EAAA,EAAA,SAAA,KAAuB,EAAqB,MAAM,MAAO,GAAM,EAAE,KAAK,CAsCM,CAAM,CAC1F"}
|
package/dist/forms/context.d.ts
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { type Readable } from '@vielzeug/ripple';
|
|
2
|
-
/**
|
|
3
|
-
* Context shape injected by child field components.
|
|
4
|
-
* Contains only what a field needs — not submit/error/status APIs.
|
|
5
|
-
*/
|
|
6
|
-
export type FormFieldContext = {
|
|
7
|
-
/** Whether any field has been touched (interacted with). Set via markDirty(). */
|
|
8
|
-
readonly dirty: Readable<boolean>;
|
|
9
|
-
markDirty(): void;
|
|
10
|
-
/**
|
|
11
|
-
* Register a field's validity signal with the form context.
|
|
12
|
-
* Returns a cleanup function.
|
|
13
|
-
*/
|
|
14
|
-
registerField(validity: Readable<boolean>): () => void;
|
|
15
|
-
};
|
|
16
|
-
/**
|
|
17
|
-
* Full form controller returned by `createFormContext`.
|
|
18
|
-
* Extends `FormFieldContext` with submission and status APIs.
|
|
19
|
-
*/
|
|
20
|
-
export type FormController = FormFieldContext & {
|
|
21
|
-
/**
|
|
22
|
-
* Clear `dirty` and `error` status signals and invoke `onReset` if provided.
|
|
23
|
-
* Note: this does not reset individual field values — pass an `onReset` callback
|
|
24
|
-
* to handle value restoration.
|
|
25
|
-
*/
|
|
26
|
-
clearStatus(): void;
|
|
27
|
-
/** The last submit error, or null if the last submit succeeded. */
|
|
28
|
-
readonly error: Readable<unknown>;
|
|
29
|
-
/** Submit the form programmatically. */
|
|
30
|
-
submit(e?: Event): Promise<void>;
|
|
31
|
-
/** Whether the form is currently submitting. */
|
|
32
|
-
readonly submitting: Readable<boolean>;
|
|
33
|
-
/** Whether all fields in the form are valid. */
|
|
34
|
-
readonly valid: Readable<boolean>;
|
|
35
|
-
};
|
|
36
|
-
export declare const FORM_CONTEXT_KEY: import("..").InjectionKey<FormFieldContext>;
|
|
37
|
-
/**
|
|
38
|
-
* Create a `FormController` for coordinating form state across child field components.
|
|
39
|
-
* Call `provide(FORM_CONTEXT_KEY, form)` to make it available to descendants.
|
|
40
|
-
*
|
|
41
|
-
* @example
|
|
42
|
-
* ```ts
|
|
43
|
-
* define('my-form', {
|
|
44
|
-
* setup(_props) {
|
|
45
|
-
* const form = createFormContext({ onSubmit: async (e) => { ... } });
|
|
46
|
-
* provide(FORM_CONTEXT_KEY, form);
|
|
47
|
-
* return html`<form @submit=${form.submit}><slot></slot></form>`;
|
|
48
|
-
* }
|
|
49
|
-
* });
|
|
50
|
-
* ```
|
|
51
|
-
*/
|
|
52
|
-
export declare function createFormContext(options?: {
|
|
53
|
-
onReset?: () => void;
|
|
54
|
-
onSubmit?: (e?: Event) => void | Promise<void>;
|
|
55
|
-
}): FormController;
|
|
56
|
-
//# sourceMappingURL=context.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/forms/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,QAAQ,EAAU,MAAM,kBAAkB,CAAC;AAInE;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,iFAAiF;IACjF,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;IAClC,SAAS,IAAI,IAAI,CAAC;IAClB;;;OAGG;IACH,aAAa,CAAC,QAAQ,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,MAAM,IAAI,CAAC;CACxD,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,gBAAgB,GAAG;IAC9C;;;;OAIG;IACH,WAAW,IAAI,IAAI,CAAC;IACpB,mEAAmE;IACnE,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;IAClC,wCAAwC;IACxC,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,gDAAgD;IAChD,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;IACvC,gDAAgD;IAChD,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;CACnC,CAAC;AAEF,eAAO,MAAM,gBAAgB,6CAAsD,CAAC;AAEpF;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,GAAE;IACP,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3C,GACL,cAAc,CA+ChB"}
|
package/dist/forms/context.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{createContext as e}from"../context.js";import{computed as t,signal as n}from"@vielzeug/ripple";var r=e(`ore:form-context`);function i(e={}){let r=n([]),i=n(!1),a=n(!1),o=n(null);return{clearStatus:()=>{a.value=!1,o.value=null,e.onReset?.()},dirty:a,error:o,markDirty:()=>{a.value=!0},registerField:e=>(r.value=[...r.value,e],()=>{r.value=r.value.filter(t=>t!==e)}),submit:async t=>{if(t?.preventDefault(),!i.value){i.value=!0,o.value=null;try{await e.onSubmit?.(t),a.value=!1}catch(e){o.value=e}finally{i.value=!1}}},submitting:i,valid:t(()=>r.value.every(e=>e.value))}}export{r as FORM_CONTEXT_KEY,i as createFormContext};
|
|
2
|
-
//# sourceMappingURL=context.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"context.js","names":[],"sources":["../../src/forms/context.ts"],"sourcesContent":["import { computed, type Readable, signal } from '@vielzeug/ripple';\n\nimport { createContext } from '../context';\n\n/**\n * Context shape injected by child field components.\n * Contains only what a field needs — not submit/error/status APIs.\n */\nexport type FormFieldContext = {\n /** Whether any field has been touched (interacted with). Set via markDirty(). */\n readonly dirty: Readable<boolean>;\n markDirty(): void;\n /**\n * Register a field's validity signal with the form context.\n * Returns a cleanup function.\n */\n registerField(validity: Readable<boolean>): () => void;\n};\n\n/**\n * Full form controller returned by `createFormContext`.\n * Extends `FormFieldContext` with submission and status APIs.\n */\nexport type FormController = FormFieldContext & {\n /**\n * Clear `dirty` and `error` status signals and invoke `onReset` if provided.\n * Note: this does not reset individual field values — pass an `onReset` callback\n * to handle value restoration.\n */\n clearStatus(): void;\n /** The last submit error, or null if the last submit succeeded. */\n readonly error: Readable<unknown>;\n /** Submit the form programmatically. */\n submit(e?: Event): Promise<void>;\n /** Whether the form is currently submitting. */\n readonly submitting: Readable<boolean>;\n /** Whether all fields in the form are valid. */\n readonly valid: Readable<boolean>;\n};\n\nexport const FORM_CONTEXT_KEY = createContext<FormFieldContext>('ore:form-context');\n\n/**\n * Create a `FormController` for coordinating form state across child field components.\n * Call `provide(FORM_CONTEXT_KEY, form)` to make it available to descendants.\n *\n * @example\n * ```ts\n * define('my-form', {\n * setup(_props) {\n * const form = createFormContext({ onSubmit: async (e) => { ... } });\n * provide(FORM_CONTEXT_KEY, form);\n * return html`<form @submit=${form.submit}><slot></slot></form>`;\n * }\n * });\n * ```\n */\nexport function createFormContext(\n options: {\n onReset?: () => void;\n onSubmit?: (e?: Event) => void | Promise<void>;\n } = {},\n): FormController {\n const fieldValiditySignals = signal<Array<Readable<boolean>>>([]);\n const submitting = signal(false);\n const dirty = signal(false);\n const error = signal<unknown>(null);\n\n // Note: [].every() is vacuously true, so valid is true when no fields are registered.\n // This is intentional — a form with no fields is considered valid (nothing to invalidate it).\n const valid = computed(() => fieldValiditySignals.value.every((s) => s.value));\n\n const submit = async (e?: Event): Promise<void> => {\n e?.preventDefault();\n\n if (submitting.value) return;\n\n submitting.value = true;\n error.value = null;\n\n try {\n await options.onSubmit?.(e);\n dirty.value = false;\n } catch (err) {\n error.value = err;\n } finally {\n submitting.value = false;\n }\n };\n\n const clearStatus = (): void => {\n dirty.value = false;\n error.value = null;\n options.onReset?.();\n };\n\n const markDirty = (): void => {\n dirty.value = true;\n };\n\n const registerField = (validity: Readable<boolean>): (() => void) => {\n fieldValiditySignals.value = [...fieldValiditySignals.value, validity];\n\n return () => {\n fieldValiditySignals.value = fieldValiditySignals.value.filter((s) => s !== validity);\n };\n };\n\n return { clearStatus, dirty, error, markDirty, registerField, submit, submitting, valid };\n}\n"],"mappings":"sGAwCA,IAAa,EAAmB,EAAgC,kBAAkB,EAiBlF,SAAgB,EACd,EAGI,CAAC,EACW,CAChB,IAAM,EAAuB,EAAiC,CAAC,CAAC,EAC1D,EAAa,EAAO,EAAK,EACzB,EAAQ,EAAO,EAAK,EACpB,EAAQ,EAAgB,IAAI,EA0ClC,MAAO,CAAE,gBAlBuB,CAC9B,EAAM,MAAQ,GACd,EAAM,MAAQ,KACd,EAAQ,UAAU,CACpB,EAcsB,QAAO,QAAO,cAZN,CAC5B,EAAM,MAAQ,EAChB,EAU+C,cARxB,IACrB,EAAqB,MAAQ,CAAC,GAAG,EAAqB,MAAO,CAAQ,MAExD,CACX,EAAqB,MAAQ,EAAqB,MAAM,OAAQ,GAAM,IAAM,CAAQ,CACtF,GAG4D,YApCxC,IAA6B,CACjD,MAAG,eAAe,EAEd,GAAW,MAGf,CADA,EAAW,MAAQ,GACnB,EAAM,MAAQ,KAEd,GAAI,CACF,MAAM,EAAQ,WAAW,CAAC,EAC1B,EAAM,MAAQ,EAChB,OAAS,EAAK,CACZ,EAAM,MAAQ,CAChB,QAAU,CACR,EAAW,MAAQ,EACrB,CATc,CAUhB,EAoBsE,aAAY,MAtCpE,MAAe,EAAqB,MAAM,MAAO,GAAM,EAAE,KAAK,CAsCM,CAAM,CAC1F"}
|
package/dist/forms/index.d.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Form-association helpers built on `ElementInternals`.
|
|
3
|
-
*
|
|
4
|
-
* Split from the package root into its own sub-path: not every component
|
|
5
|
-
* needs `formAssociated`/`ElementInternals` wiring, and keeping it out of the
|
|
6
|
-
* core surface keeps `@vielzeug/ore`'s main entry point scoped to universal
|
|
7
|
-
* authoring primitives (define/html/prop/context/aria).
|
|
8
|
-
*/
|
|
9
|
-
export { useField, type FormFieldHandle, type FormFieldOptions } from './field';
|
|
10
|
-
export { createFormContext, FORM_CONTEXT_KEY, type FormController, type FormFieldContext } from './context';
|
|
11
|
-
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/forms/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,QAAQ,EAAE,KAAK,eAAe,EAAE,KAAK,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAChF,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,KAAK,cAAc,EAAE,KAAK,gBAAgB,EAAE,MAAM,WAAW,CAAC"}
|
package/dist/forms.cjs
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./forms/field.cjs"),t=require("./forms/context.cjs");exports.FORM_CONTEXT_KEY=t.FORM_CONTEXT_KEY,exports.createFormContext=t.createFormContext,exports.useField=e.useField;
|
package/dist/forms.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{useField as e}from"./forms/field.js";import{FORM_CONTEXT_KEY as t,createFormContext as n}from"./forms/context.js";export{t as FORM_CONTEXT_KEY,n as createFormContext,e as useField};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/observers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC"}
|
package/dist/observers.cjs
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./observers/intersection-observe.cjs"),t=require("./observers/media-observe.cjs"),n=require("./observers/mutation-observe.cjs"),r=require("./observers/resize-observe.cjs");exports.intersectionObserver=e.intersectionObserver,exports.mediaObserver=t.mediaObserver,exports.mutationObserver=n.mutationObserver,exports.resizeObserver=r.resizeObserver;
|
package/dist/observers.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{intersectionObserver as e}from"./observers/intersection-observe.js";import{mediaObserver as t}from"./observers/media-observe.js";import{mutationObserver as n}from"./observers/mutation-observe.js";import{resizeObserver as r}from"./observers/resize-observe.js";export{e as intersectionObserver,t as mediaObserver,n as mutationObserver,r as resizeObserver};
|
package/dist/template.cjs
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
require("./template/bindings.cjs");const e=require("./template/instantiator.cjs");exports.html=e.html;
|
package/dist/template.d.ts
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
export { applyAttrBinding, applyBinding, applyHtmlBinding, type RegisterCleanup } from './template/bindings';
|
|
2
|
-
export { type CompiledStaticTemplate, type NodePath, type SlotMeta } from './template/compiler';
|
|
3
|
-
export { compileTemplate, html } from './template/instantiator';
|
|
4
|
-
//# sourceMappingURL=template.d.ts.map
|
package/dist/template.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../src/template.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,gBAAgB,EAAE,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC7G,OAAO,EAAE,KAAK,sBAAsB,EAAE,KAAK,QAAQ,EAAE,KAAK,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAChG,OAAO,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAC"}
|
package/dist/template.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import"./template/bindings.js";import{html as e}from"./template/instantiator.js";export{e as html};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
const e=require("./flush.cjs");let t=require("@vielzeug/assay");var n=()=>e.flush(),r={async clear(e){e.focus(),e.value=``,t.fire.input(e),t.fire.change(e),await n()},async click(e,r){t.fire.pointerEnter(e,r),t.fire.click(e,r),await n()},async dblClick(e){for(let n=0;n<2;n++)t.fire.pointerDown(e),t.fire.pointerUp(e),t.fire.click(e);e.dispatchEvent(new MouseEvent(`dblclick`,{bubbles:!0,cancelable:!0})),await n()},async fill(e,r){e.focus(),e.value=``;for(let i of r)e.value+=i,t.fire.input(e),t.fire.keyDown(e,{key:i}),t.fire.keyUp(e,{key:i}),await n();t.fire.change(e)},async hover(e){t.fire.pointerEnter(e),await n()},async press(e,r,i){t.fire.keyDown(e,{key:r,...i}),t.fire.keyUp(e,{key:r,...i}),await n()},async select(e,r){let i=Array.isArray(r)?r:[r];for(let t of e.options)t.selected=i.includes(t.value);t.fire.change(e),await n()},async type(e,r){e.focus();for(let i of r)e.value+=i,t.fire.input(e),t.fire.keyDown(e,{key:i}),t.fire.keyUp(e,{key:i}),await n();t.fire.change(e)},async unhover(e){t.fire.pointerLeave(e),await n()}};exports.user=r;
|
|
2
|
-
//# sourceMappingURL=interactions.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"interactions.cjs","names":[],"sources":["../../src/testing/interactions.ts"],"sourcesContent":["/**\n * Higher-level async user interaction helpers for test environments.\n */\n\nimport { fire } from '@vielzeug/assay';\n\nimport { flush } from './flush';\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\nconst tick = (): Promise<void> => flush();\n\n// ─── API ─────────────────────────────────────────────────────────────────────\n\n/**\n * Higher-level async user interactions that mirror real browser behavior.\n *\n * @example\n * await user.type(input, 'hello');\n * await user.fill(input, 'replacement'); // clear then type\n * await user.click(button);\n * await user.press(input, 'Enter');\n */\nexport const user = {\n async clear(el: HTMLInputElement | HTMLTextAreaElement): Promise<void> {\n el.focus();\n el.value = '';\n fire.input(el);\n fire.change(el);\n await tick();\n },\n\n async click(el: Element, opts?: PointerEventInit): Promise<void> {\n fire.pointerEnter(el, opts);\n fire.click(el, opts);\n await tick();\n },\n\n async dblClick(el: Element): Promise<void> {\n for (let i = 0; i < 2; i++) {\n fire.pointerDown(el);\n fire.pointerUp(el);\n fire.click(el);\n }\n el.dispatchEvent(new MouseEvent('dblclick', { bubbles: true, cancelable: true }));\n await tick();\n },\n\n /** Clear existing value and type new text (select-all-and-replace semantics) */\n async fill(el: HTMLInputElement | HTMLTextAreaElement, text: string): Promise<void> {\n el.focus();\n el.value = '';\n for (const char of text) {\n el.value += char;\n fire.input(el);\n fire.keyDown(el, { key: char });\n fire.keyUp(el, { key: char });\n await tick();\n }\n fire.change(el);\n },\n\n async hover(el: Element): Promise<void> {\n fire.pointerEnter(el);\n await tick();\n },\n\n /** Dispatch keydown + keyup for a single key */\n async press(el: Element, key: string, opts?: KeyboardEventInit): Promise<void> {\n fire.keyDown(el, { key, ...opts });\n fire.keyUp(el, { key, ...opts });\n await tick();\n },\n\n async select(el: HTMLSelectElement, value: string | string[]): Promise<void> {\n const values = Array.isArray(value) ? value : [value];\n\n for (const opt of el.options) opt.selected = values.includes(opt.value);\n fire.change(el);\n await tick();\n },\n\n /** Type text character-by-character, appending to any existing value */\n async type(el: HTMLInputElement | HTMLTextAreaElement, text: string): Promise<void> {\n el.focus();\n for (const char of text) {\n el.value += char;\n fire.input(el);\n fire.keyDown(el, { key: char });\n fire.keyUp(el, { key: char });\n await tick();\n }\n fire.change(el);\n },\n\n async unhover(el: Element): Promise<void> {\n fire.pointerLeave(el);\n await tick();\n },\n} as const;\n"],"mappings":"gEAUA,IAAM,MAA4B,EAAA,MAAM,EAa3B,EAAO,CAClB,MAAM,MAAM,EAA2D,CACrE,EAAG,MAAM,EACT,EAAG,MAAQ,GACX,EAAA,KAAK,MAAM,CAAE,EACb,EAAA,KAAK,OAAO,CAAE,EACd,MAAM,EAAK,CACb,EAEA,MAAM,MAAM,EAAa,EAAwC,CAC/D,EAAA,KAAK,aAAa,EAAI,CAAI,EAC1B,EAAA,KAAK,MAAM,EAAI,CAAI,EACnB,MAAM,EAAK,CACb,EAEA,MAAM,SAAS,EAA4B,CACzC,IAAK,IAAI,EAAI,EAAG,EAAI,EAAG,IACrB,EAAA,KAAK,YAAY,CAAE,EACnB,EAAA,KAAK,UAAU,CAAE,EACjB,EAAA,KAAK,MAAM,CAAE,EAEf,EAAG,cAAc,IAAI,WAAW,WAAY,CAAE,QAAS,GAAM,WAAY,EAAK,CAAC,CAAC,EAChF,MAAM,EAAK,CACb,EAGA,MAAM,KAAK,EAA4C,EAA6B,CAClF,EAAG,MAAM,EACT,EAAG,MAAQ,GACX,IAAK,IAAM,KAAQ,EACjB,EAAG,OAAS,EACZ,EAAA,KAAK,MAAM,CAAE,EACb,EAAA,KAAK,QAAQ,EAAI,CAAE,IAAK,CAAK,CAAC,EAC9B,EAAA,KAAK,MAAM,EAAI,CAAE,IAAK,CAAK,CAAC,EAC5B,MAAM,EAAK,EAEb,EAAA,KAAK,OAAO,CAAE,CAChB,EAEA,MAAM,MAAM,EAA4B,CACtC,EAAA,KAAK,aAAa,CAAE,EACpB,MAAM,EAAK,CACb,EAGA,MAAM,MAAM,EAAa,EAAa,EAAyC,CAC7E,EAAA,KAAK,QAAQ,EAAI,CAAE,MAAK,GAAG,CAAK,CAAC,EACjC,EAAA,KAAK,MAAM,EAAI,CAAE,MAAK,GAAG,CAAK,CAAC,EAC/B,MAAM,EAAK,CACb,EAEA,MAAM,OAAO,EAAuB,EAAyC,CAC3E,IAAM,EAAS,MAAM,QAAQ,CAAK,EAAI,EAAQ,CAAC,CAAK,EAEpD,IAAK,IAAM,KAAO,EAAG,QAAS,EAAI,SAAW,EAAO,SAAS,EAAI,KAAK,EACtE,EAAA,KAAK,OAAO,CAAE,EACd,MAAM,EAAK,CACb,EAGA,MAAM,KAAK,EAA4C,EAA6B,CAClF,EAAG,MAAM,EACT,IAAK,IAAM,KAAQ,EACjB,EAAG,OAAS,EACZ,EAAA,KAAK,MAAM,CAAE,EACb,EAAA,KAAK,QAAQ,EAAI,CAAE,IAAK,CAAK,CAAC,EAC9B,EAAA,KAAK,MAAM,EAAI,CAAE,IAAK,CAAK,CAAC,EAC5B,MAAM,EAAK,EAEb,EAAA,KAAK,OAAO,CAAE,CAChB,EAEA,MAAM,QAAQ,EAA4B,CACxC,EAAA,KAAK,aAAa,CAAE,EACpB,MAAM,EAAK,CACb,CACF"}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Higher-level async user interaction helpers for test environments.
|
|
3
|
-
*/
|
|
4
|
-
/**
|
|
5
|
-
* Higher-level async user interactions that mirror real browser behavior.
|
|
6
|
-
*
|
|
7
|
-
* @example
|
|
8
|
-
* await user.type(input, 'hello');
|
|
9
|
-
* await user.fill(input, 'replacement'); // clear then type
|
|
10
|
-
* await user.click(button);
|
|
11
|
-
* await user.press(input, 'Enter');
|
|
12
|
-
*/
|
|
13
|
-
export declare const user: {
|
|
14
|
-
readonly clear: (el: HTMLInputElement | HTMLTextAreaElement) => Promise<void>;
|
|
15
|
-
readonly click: (el: Element, opts?: PointerEventInit) => Promise<void>;
|
|
16
|
-
readonly dblClick: (el: Element) => Promise<void>;
|
|
17
|
-
/** Clear existing value and type new text (select-all-and-replace semantics) */
|
|
18
|
-
readonly fill: (el: HTMLInputElement | HTMLTextAreaElement, text: string) => Promise<void>;
|
|
19
|
-
readonly hover: (el: Element) => Promise<void>;
|
|
20
|
-
/** Dispatch keydown + keyup for a single key */
|
|
21
|
-
readonly press: (el: Element, key: string, opts?: KeyboardEventInit) => Promise<void>;
|
|
22
|
-
readonly select: (el: HTMLSelectElement, value: string | string[]) => Promise<void>;
|
|
23
|
-
/** Type text character-by-character, appending to any existing value */
|
|
24
|
-
readonly type: (el: HTMLInputElement | HTMLTextAreaElement, text: string) => Promise<void>;
|
|
25
|
-
readonly unhover: (el: Element) => Promise<void>;
|
|
26
|
-
};
|
|
27
|
-
//# sourceMappingURL=interactions.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"interactions.d.ts","sourceRoot":"","sources":["../../src/testing/interactions.ts"],"names":[],"mappings":"AAAA;;GAEG;AAYH;;;;;;;;GAQG;AACH,eAAO,MAAM,IAAI;yBACC,gBAAgB,GAAG,mBAAmB,KAAG,OAAO,CAAC,IAAI,CAAC;yBAQtD,OAAO,SAAS,gBAAgB,KAAG,OAAO,CAAC,IAAI,CAAC;4BAM7C,OAAO,KAAG,OAAO,CAAC,IAAI,CAAC;IAU1C,gFAAgF;wBACjE,gBAAgB,GAAG,mBAAmB,QAAQ,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC;yBAanE,OAAO,KAAG,OAAO,CAAC,IAAI,CAAC;IAKvC,gDAAgD;yBAChC,OAAO,OAAO,MAAM,SAAS,iBAAiB,KAAG,OAAO,CAAC,IAAI,CAAC;0BAM7D,iBAAiB,SAAS,MAAM,GAAG,MAAM,EAAE,KAAG,OAAO,CAAC,IAAI,CAAC;IAQ5E,wEAAwE;wBACzD,gBAAgB,GAAG,mBAAmB,QAAQ,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC;2BAYjE,OAAO,KAAG,OAAO,CAAC,IAAI,CAAC;CAIjC,CAAC"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{flush as e}from"./flush.js";import{fire as t}from"@vielzeug/assay";var n=()=>e(),r={async clear(e){e.focus(),e.value=``,t.input(e),t.change(e),await n()},async click(e,r){t.pointerEnter(e,r),t.click(e,r),await n()},async dblClick(e){for(let n=0;n<2;n++)t.pointerDown(e),t.pointerUp(e),t.click(e);e.dispatchEvent(new MouseEvent(`dblclick`,{bubbles:!0,cancelable:!0})),await n()},async fill(e,r){e.focus(),e.value=``;for(let i of r)e.value+=i,t.input(e),t.keyDown(e,{key:i}),t.keyUp(e,{key:i}),await n();t.change(e)},async hover(e){t.pointerEnter(e),await n()},async press(e,r,i){t.keyDown(e,{key:r,...i}),t.keyUp(e,{key:r,...i}),await n()},async select(e,r){let i=Array.isArray(r)?r:[r];for(let t of e.options)t.selected=i.includes(t.value);t.change(e),await n()},async type(e,r){e.focus();for(let i of r)e.value+=i,t.input(e),t.keyDown(e,{key:i}),t.keyUp(e,{key:i}),await n();t.change(e)},async unhover(e){t.pointerLeave(e),await n()}};export{r as user};
|
|
2
|
-
//# sourceMappingURL=interactions.js.map
|