@vizejs/ui 0.302.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.
@@ -0,0 +1,8 @@
1
+ //#region \0plugin-vue:export-helper
2
+ var _plugin_vue_export_helper_default = (sfc, props) => {
3
+ const target = sfc.__vccOpts || sfc;
4
+ for (const [key, val] of props) target[key] = val;
5
+ return target;
6
+ };
7
+ //#endregion
8
+ export { _plugin_vue_export_helper_default as t };
@@ -0,0 +1,126 @@
1
+ import { t as _plugin_vue_export_helper_default } from "./_plugin-vue_export-helper-BVN2DL-U.mjs";
2
+ import { computed, createBlock, defineComponent, openBlock, renderSlot, resolveDynamicComponent, useTemplateRef, withCtx } from "vue";
3
+ //#region src/button-keyboard.ts
4
+ /**
5
+ * Resolve native-equivalent activation timing for a non-native button.
6
+ *
7
+ * Enter activates on keydown. Space prevents scrolling on keydown and
8
+ * activates on keyup, matching the interaction users expect from a button.
9
+ */
10
+ function getButtonKeyboardAction(key, phase) {
11
+ if (key === "Enter") return phase === "keydown" ? "activate" : "ignore";
12
+ if (key === " ") return phase === "keydown" ? "prevent" : "activate";
13
+ return "ignore";
14
+ }
15
+ //#endregion
16
+ //#region src/ActionButton.vue
17
+ var ActionButton_default = /* @__PURE__ */ _plugin_vue_export_helper_default(/* @__PURE__ */ defineComponent({
18
+ __name: "ActionButton",
19
+ props: {
20
+ as: {
21
+ type: null,
22
+ required: false,
23
+ default: "button"
24
+ },
25
+ native: {
26
+ type: Boolean,
27
+ required: false
28
+ },
29
+ type: {
30
+ type: String,
31
+ required: false,
32
+ default: "button"
33
+ },
34
+ disabled: {
35
+ type: Boolean,
36
+ required: false,
37
+ default: false
38
+ },
39
+ loading: {
40
+ type: Boolean,
41
+ required: false,
42
+ default: false
43
+ }
44
+ },
45
+ emits: ["press"],
46
+ setup(__props, { expose: __expose, emit: __emit }) {
47
+ const emit = __emit;
48
+ const element = useTemplateRef("element");
49
+ const isNativeButton = computed(() => __props.native ?? __props.as === "button");
50
+ const unavailable = computed(() => __props.disabled || __props.loading);
51
+ const tabIndex = computed(() => {
52
+ if (isNativeButton.value) return void 0;
53
+ return __props.disabled ? -1 : 0;
54
+ });
55
+ function onClick(event) {
56
+ if (unavailable.value) {
57
+ event.preventDefault();
58
+ event.stopImmediatePropagation();
59
+ return;
60
+ }
61
+ emit("press", event);
62
+ }
63
+ function onKeyboard(event, phase) {
64
+ if (isNativeButton.value) return;
65
+ const action = getButtonKeyboardAction(event.key, phase);
66
+ if (action === "ignore") return;
67
+ event.preventDefault();
68
+ if (unavailable.value) {
69
+ event.stopImmediatePropagation();
70
+ return;
71
+ }
72
+ if (action === "activate" && event.currentTarget instanceof HTMLElement) event.currentTarget.click();
73
+ }
74
+ function onKeydown(event) {
75
+ onKeyboard(event, "keydown");
76
+ }
77
+ function onKeyup(event) {
78
+ onKeyboard(event, "keyup");
79
+ }
80
+ /** Move focus to the rendered control when it exposes a focus method. */
81
+ function focus(options) {
82
+ focusTarget(element.value, options);
83
+ }
84
+ function focusTarget(target, options) {
85
+ if (typeof target === "object" && target !== null && "focus" in target && typeof target.focus === "function") target.focus(options);
86
+ }
87
+ __expose({
88
+ element,
89
+ focus
90
+ });
91
+ return (_ctx, _cache) => {
92
+ return openBlock(), createBlock(resolveDynamicComponent(__props.as), {
93
+ ref_key: "element",
94
+ ref: element,
95
+ type: isNativeButton.value ? __props.type : void 0,
96
+ disabled: isNativeButton.value ? __props.disabled : void 0,
97
+ role: isNativeButton.value ? void 0 : "button",
98
+ tabindex: tabIndex.value,
99
+ "aria-disabled": unavailable.value && (!isNativeButton.value || __props.loading) ? "true" : void 0,
100
+ "aria-busy": __props.loading ? "true" : void 0,
101
+ "data-vize-ui": "button",
102
+ "data-state": __props.disabled ? "disabled" : __props.loading ? "loading" : "idle",
103
+ onClick,
104
+ onKeydown,
105
+ onKeyup
106
+ }, {
107
+ default: withCtx(() => [renderSlot(_ctx.$slots, "default", {
108
+ disabled: __props.disabled,
109
+ loading: __props.loading,
110
+ unavailable: unavailable.value
111
+ }, void 0, true)]),
112
+ _: 3
113
+ }, 40, [
114
+ "type",
115
+ "disabled",
116
+ "role",
117
+ "tabindex",
118
+ "aria-disabled",
119
+ "aria-busy",
120
+ "data-state"
121
+ ]);
122
+ };
123
+ }
124
+ }), [["__scopeId", "data-v-0ffc2dd9"]]);
125
+ //#endregion
126
+ export { getButtonKeyboardAction as n, ActionButton_default as t };
@@ -0,0 +1,75 @@
1
+ import { n as PrimitiveElement, t as PrimitiveAs } from "./primitive-BtvwikH1.mjs";
2
+ import * as _$vue from "vue";
3
+
4
+ //#region src/button-keyboard.d.ts
5
+ /** Keyboard event phase used by button activation semantics. */
6
+ type ButtonKeyboardPhase = "keydown" | "keyup";
7
+ /** Action required to emulate a native button for one keyboard event. */
8
+ type ButtonKeyboardAction = "activate" | "prevent" | "ignore";
9
+ /**
10
+ * Resolve native-equivalent activation timing for a non-native button.
11
+ *
12
+ * Enter activates on keydown. Space prevents scrolling on keydown and
13
+ * activates on keyup, matching the interaction users expect from a button.
14
+ */
15
+ declare function getButtonKeyboardAction(key: string, phase: ButtonKeyboardPhase): ButtonKeyboardAction;
16
+ //#endregion
17
+ //#region src/ActionButton.vue.d.ts
18
+ type __VLS_Props = {
19
+ /**
20
+ * Native element, custom element, or component to render.
21
+ *
22
+ * @default "button"
23
+ */
24
+ readonly as?: PrimitiveAs;
25
+ /**
26
+ * Whether the rendered target already implements native button semantics.
27
+ *
28
+ * @default true when `as` is "button"; otherwise false
29
+ */
30
+ readonly native?: boolean;
31
+ /**
32
+ * Native button submission behavior.
33
+ *
34
+ * @default "button"
35
+ */
36
+ readonly type?: "button" | "reset" | "submit";
37
+ /**
38
+ * Remove the control from activation and sequential keyboard focus.
39
+ *
40
+ * @default false
41
+ */
42
+ readonly disabled?: boolean;
43
+ /**
44
+ * Announce in-progress work and prevent repeated activation while preserving focus.
45
+ *
46
+ * @default false
47
+ */
48
+ readonly loading?: boolean;
49
+ };
50
+ type __VLS_Slots = {
51
+ default(props: {
52
+ readonly disabled: boolean;
53
+ readonly loading: boolean;
54
+ readonly unavailable: boolean;
55
+ }): unknown;
56
+ };
57
+ /** Move focus to the rendered control when it exposes a focus method. */
58
+ declare function focus(options?: FocusOptions): void;
59
+ declare const __VLS_base: _$vue.DefineComponent<__VLS_Props, {
60
+ element: Readonly<_$vue.ShallowRef<PrimitiveElement | null>>;
61
+ focus: typeof focus;
62
+ }, {}, {}, {}, _$vue.ComponentOptionsMixin, _$vue.ComponentOptionsMixin, {
63
+ press: (event: MouseEvent) => any;
64
+ }, string, _$vue.PublicProps, Readonly<__VLS_Props> & Readonly<{
65
+ onPress?: (event: MouseEvent) => any;
66
+ }>, {}, {}, {}, {}, string, _$vue.ComponentProvideOptions, false, {}, any>;
67
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
68
+ declare const _default: typeof __VLS_export;
69
+ type __VLS_WithSlots<T, S> = T & {
70
+ new (): {
71
+ $slots: S;
72
+ };
73
+ };
74
+ //#endregion
75
+ export { getButtonKeyboardAction as i, ButtonKeyboardAction as n, ButtonKeyboardPhase as r, _default as t };
@@ -0,0 +1,2 @@
1
+ import { i as getButtonKeyboardAction, n as ButtonKeyboardAction, r as ButtonKeyboardPhase, t as _default } from "./button-D7sM9Xmj.mjs";
2
+ export { _default as Button, ButtonKeyboardAction, ButtonKeyboardPhase, getButtonKeyboardAction };
@@ -0,0 +1,2 @@
1
+ import { n as getButtonKeyboardAction, t as ActionButton_default } from "./button-BcfUlpr_.mjs";
2
+ export { ActionButton_default as Button, getButtonKeyboardAction };
@@ -0,0 +1,118 @@
1
+ import { useControllableState } from "./controllable-state.mjs";
2
+ import { t as _plugin_vue_export_helper_default } from "./_plugin-vue_export-helper-BVN2DL-U.mjs";
3
+ import { computed, createElementBlock, defineComponent, nextTick, openBlock, unref, useTemplateRef, watch, watchEffect } from "vue";
4
+ //#region src/checkbox-state.ts
5
+ /** Resolve the visual state while giving the mixed state precedence. */
6
+ function getCheckboxState(checked, indeterminate) {
7
+ if (indeterminate) return "indeterminate";
8
+ return checked ? "checked" : "unchecked";
9
+ }
10
+ //#endregion
11
+ //#region src/CheckboxControl.vue?vue&type=script&setup=true&lang.ts
12
+ const _hoisted_1 = [
13
+ "checked",
14
+ "disabled",
15
+ "aria-label",
16
+ "aria-checked",
17
+ "data-state"
18
+ ];
19
+ //#endregion
20
+ //#region src/CheckboxControl.vue
21
+ var CheckboxControl_default = /* @__PURE__ */ _plugin_vue_export_helper_default(/* @__PURE__ */ defineComponent({
22
+ __name: "CheckboxControl",
23
+ props: {
24
+ modelValue: {
25
+ type: Boolean,
26
+ required: false
27
+ },
28
+ defaultChecked: {
29
+ type: Boolean,
30
+ required: false,
31
+ default: false
32
+ },
33
+ indeterminate: {
34
+ type: Boolean,
35
+ required: false,
36
+ default: false
37
+ },
38
+ disabled: {
39
+ type: Boolean,
40
+ required: false,
41
+ default: false
42
+ },
43
+ ariaLabel: {
44
+ type: String,
45
+ required: false
46
+ }
47
+ },
48
+ emits: [
49
+ "update:modelValue",
50
+ "update:indeterminate",
51
+ "change"
52
+ ],
53
+ setup(__props, { expose: __expose, emit: __emit }) {
54
+ const emit = __emit;
55
+ const element = useTemplateRef("element");
56
+ const state = useControllableState({
57
+ value: () => __props.modelValue,
58
+ defaultValue: () => __props.defaultChecked,
59
+ onChange: (value) => emit("update:modelValue", value)
60
+ });
61
+ const checked = state.value;
62
+ const visualState = computed(() => getCheckboxState(checked.value, __props.indeterminate));
63
+ function syncNativeState() {
64
+ if (element.value === null) return;
65
+ element.value.checked = checked.value;
66
+ element.value.indeterminate = __props.indeterminate;
67
+ }
68
+ watchEffect(syncNativeState);
69
+ watch(element, (input, _previous, onCleanup) => {
70
+ const form = input?.form;
71
+ if (form === void 0 || form === null) return;
72
+ const onReset = () => {
73
+ if (!state.controlled.value) state.reset();
74
+ nextTick(syncNativeState);
75
+ };
76
+ form.addEventListener("reset", onReset);
77
+ onCleanup(() => form.removeEventListener("reset", onReset));
78
+ }, {
79
+ flush: "post",
80
+ immediate: true
81
+ });
82
+ function onChange(event) {
83
+ if (!(event.currentTarget instanceof HTMLInputElement)) return;
84
+ const next = event.currentTarget.checked;
85
+ state.set(next);
86
+ if (__props.indeterminate) emit("update:indeterminate", false);
87
+ emit("change", next, event);
88
+ nextTick(syncNativeState);
89
+ }
90
+ /** Move focus to the native checkbox. */
91
+ function focus(options) {
92
+ element.value?.focus(options);
93
+ }
94
+ __expose({
95
+ element,
96
+ checked,
97
+ focus,
98
+ reset: state.reset,
99
+ setChecked: state.set
100
+ });
101
+ return (_ctx, _cache) => {
102
+ return openBlock(), createElementBlock("input", {
103
+ ref_key: "element",
104
+ ref: element,
105
+ type: "checkbox",
106
+ checked: unref(checked),
107
+ disabled: __props.disabled,
108
+ "aria-label": __props.ariaLabel,
109
+ "aria-checked": __props.indeterminate ? "mixed" : unref(checked),
110
+ "data-vize-ui": "checkbox",
111
+ "data-state": visualState.value,
112
+ onChange
113
+ }, null, 40, _hoisted_1);
114
+ };
115
+ }
116
+ }), [["__scopeId", "data-v-09fed76b"]]);
117
+ //#endregion
118
+ export { getCheckboxState as n, CheckboxControl_default as t };
@@ -0,0 +1,62 @@
1
+ import { r as StateUpdate } from "./controllable-state-DXsYJ3yl.mjs";
2
+ import * as _$vue from "vue";
3
+
4
+ //#region src/checkbox-state.d.ts
5
+ /** Visual state exposed by the Checkbox Native CSS contract. */
6
+ type CheckboxState = "checked" | "unchecked" | "indeterminate";
7
+ /** Resolve the visual state while giving the mixed state precedence. */
8
+ declare function getCheckboxState(checked: boolean, indeterminate: boolean): CheckboxState;
9
+ //#endregion
10
+ //#region src/CheckboxControl.vue.d.ts
11
+ type __VLS_Props = {
12
+ /**
13
+ * Controlled checked value. `undefined` selects uncontrolled behavior.
14
+ *
15
+ * @default undefined
16
+ */
17
+ readonly modelValue?: boolean;
18
+ /**
19
+ * Initial unchecked or checked state for uncontrolled use.
20
+ *
21
+ * @default false
22
+ */
23
+ readonly defaultChecked?: boolean;
24
+ /**
25
+ * Render and announce a mixed checked state.
26
+ *
27
+ * @default false
28
+ */
29
+ readonly indeterminate?: boolean;
30
+ /**
31
+ * Disable interaction and native form submission.
32
+ *
33
+ * @default false
34
+ */
35
+ readonly disabled?: boolean;
36
+ /**
37
+ * Accessible name when no associated label supplies one.
38
+ *
39
+ * @default undefined
40
+ */
41
+ readonly ariaLabel?: string;
42
+ };
43
+ /** Move focus to the native checkbox. */
44
+ declare function focus(options?: FocusOptions): void;
45
+ declare const __VLS_export: _$vue.DefineComponent<__VLS_Props, {
46
+ element: Readonly<_$vue.ShallowRef<HTMLInputElement | null>>;
47
+ checked: _$vue.ComputedRef<boolean>;
48
+ focus: typeof focus;
49
+ reset: () => boolean;
50
+ setChecked: (update: StateUpdate<boolean>) => boolean;
51
+ }, {}, {}, {}, _$vue.ComponentOptionsMixin, _$vue.ComponentOptionsMixin, {
52
+ "update:modelValue": (value: boolean) => any;
53
+ "update:indeterminate": (value: boolean) => any;
54
+ change: (value: boolean, nativeEvent: Event) => any;
55
+ }, string, _$vue.PublicProps, Readonly<__VLS_Props> & Readonly<{
56
+ "onUpdate:modelValue"?: (value: boolean) => any;
57
+ "onUpdate:indeterminate"?: (value: boolean) => any;
58
+ onChange?: (value: boolean, nativeEvent: Event) => any;
59
+ }>, {}, {}, {}, {}, string, _$vue.ComponentProvideOptions, false, {}, any>;
60
+ declare const _default: typeof __VLS_export;
61
+ //#endregion
62
+ export { CheckboxState as n, getCheckboxState as r, _default as t };
@@ -0,0 +1,2 @@
1
+ import { n as CheckboxState, r as getCheckboxState, t as _default } from "./checkbox-DkwZFC80.mjs";
2
+ export { _default as Checkbox, CheckboxState, getCheckboxState };
@@ -0,0 +1,2 @@
1
+ import { n as getCheckboxState, t as CheckboxControl_default } from "./checkbox--QJ6FhT4.mjs";
2
+ export { CheckboxControl_default as Checkbox, getCheckboxState };
@@ -0,0 +1,25 @@
1
+ import { InjectionKey } from "vue";
2
+
3
+ //#region src/context.d.ts
4
+ /** A typed provider and consumer contract for one component family. */
5
+ interface ComponentContext<Value> {
6
+ /** Human-readable context name used by diagnostics and developer tools. */
7
+ readonly name: string;
8
+ /** Public injection key for application-level adapters and test harnesses. */
9
+ readonly key: InjectionKey<Value>;
10
+ /** Provides a value from component setup and returns that same value. */
11
+ readonly provide: (value: Value) => Value;
12
+ /** Reads the nearest value or throws a stable missing-provider diagnostic. */
13
+ readonly use: () => Value;
14
+ /** Reads the nearest value when the provider is intentionally optional. */
15
+ readonly useOptional: () => Value | undefined;
16
+ }
17
+ /**
18
+ * Creates an immutable typed context for a compound component family.
19
+ *
20
+ * A private sentinel distinguishes a missing provider from a provider whose
21
+ * value is explicitly `undefined`.
22
+ */
23
+ declare function createContext<Value>(name: string): ComponentContext<Value>;
24
+ //#endregion
25
+ export { ComponentContext, createContext };
@@ -0,0 +1,35 @@
1
+ import { inject, provide } from "vue";
2
+ //#region src/context.ts
3
+ const missingContext = Symbol("missing component context");
4
+ /**
5
+ * Creates an immutable typed context for a compound component family.
6
+ *
7
+ * A private sentinel distinguishes a missing provider from a provider whose
8
+ * value is explicitly `undefined`.
9
+ */
10
+ function createContext(name) {
11
+ const contextName = name.trim();
12
+ if (contextName.length === 0) throw new Error("VIZE_UI_CONTEXT_NAME: context name must not be empty");
13
+ const key = Symbol(contextName);
14
+ const internalKey = key;
15
+ const read = () => inject(internalKey, missingContext);
16
+ return Object.freeze({
17
+ name: contextName,
18
+ key,
19
+ provide: (value) => {
20
+ provide(key, value);
21
+ return value;
22
+ },
23
+ use: () => {
24
+ const value = read();
25
+ if (value === missingContext) throw new Error(`VIZE_UI_CONTEXT_MISSING: ${contextName} requires a matching provider`);
26
+ return value;
27
+ },
28
+ useOptional: () => {
29
+ const value = read();
30
+ return value === missingContext ? void 0 : value;
31
+ }
32
+ });
33
+ }
34
+ //#endregion
35
+ export { createContext };
@@ -0,0 +1,48 @@
1
+ import { ComputedRef, MaybeRefOrGetter } from "vue";
2
+
3
+ //#region src/controllable-state.d.ts
4
+ /** Direct value or updater accepted by {@link ControllableState.set}. */
5
+ type StateUpdate<Value> = Value | ((previous: Value) => Value);
6
+ /** Options for {@link useControllableState}. */
7
+ interface ControllableStateOptions<Value> {
8
+ /**
9
+ * Reactive controlled value. `undefined` selects uncontrolled behavior.
10
+ *
11
+ * @default undefined
12
+ */
13
+ readonly value?: MaybeRefOrGetter<Value | undefined>;
14
+ /** Initial value and the value restored by {@link ControllableState.reset}. */
15
+ readonly defaultValue: MaybeRefOrGetter<Value>;
16
+ /**
17
+ * Equality comparison used to suppress redundant updates.
18
+ *
19
+ * @default Object.is
20
+ */
21
+ readonly equals?: (left: Value, right: Value) => boolean;
22
+ /**
23
+ * Called after a distinct state change is requested.
24
+ *
25
+ * @default undefined
26
+ */
27
+ readonly onChange?: (value: Value, previous: Value) => void;
28
+ }
29
+ /** Reactive state that can move safely between controlled and uncontrolled use. */
30
+ interface ControllableState<Value> {
31
+ /** Current controlled or internal value. */
32
+ readonly value: ComputedRef<Value>;
33
+ /** Whether the reactive source currently controls the value. */
34
+ readonly controlled: ComputedRef<boolean>;
35
+ /** Request an update and report whether it differs from the current value. */
36
+ readonly set: (update: StateUpdate<Value>) => boolean;
37
+ /** Request the current default value and report whether it changed. */
38
+ readonly reset: () => boolean;
39
+ }
40
+ /**
41
+ * Create one state contract for controlled props and internal state.
42
+ *
43
+ * The last controlled value is retained if the source becomes uncontrolled,
44
+ * preventing an abrupt jump back to the initial default.
45
+ */
46
+ declare function useControllableState<Value>(options: ControllableStateOptions<Value>): ControllableState<Value>;
47
+ //#endregion
48
+ export { useControllableState as i, ControllableStateOptions as n, StateUpdate as r, ControllableState as t };
@@ -0,0 +1,2 @@
1
+ import { i as useControllableState, n as ControllableStateOptions, r as StateUpdate, t as ControllableState } from "./controllable-state-DXsYJ3yl.mjs";
2
+ export { ControllableState, ControllableStateOptions, StateUpdate, useControllableState };
@@ -0,0 +1,36 @@
1
+ import { computed, shallowRef, toValue, watch } from "vue";
2
+ //#region src/controllable-state.ts
3
+ /**
4
+ * Create one state contract for controlled props and internal state.
5
+ *
6
+ * The last controlled value is retained if the source becomes uncontrolled,
7
+ * preventing an abrupt jump back to the initial default.
8
+ */
9
+ function useControllableState(options) {
10
+ const internal = shallowRef(toValue(options.defaultValue));
11
+ const controlledValue = () => options.value === void 0 ? void 0 : toValue(options.value);
12
+ const controlled = computed(() => controlledValue() !== void 0);
13
+ const value = computed(() => controlledValue() ?? internal.value);
14
+ watch(controlledValue, (next) => {
15
+ if (next !== void 0) internal.value = next;
16
+ }, {
17
+ flush: "sync",
18
+ immediate: true
19
+ });
20
+ const set = (update) => {
21
+ const previous = value.value;
22
+ const next = typeof update === "function" ? update(previous) : update;
23
+ if ((options.equals ?? Object.is)(previous, next)) return false;
24
+ if (!controlled.value) internal.value = next;
25
+ options.onChange?.(next, previous);
26
+ return true;
27
+ };
28
+ return {
29
+ value,
30
+ controlled,
31
+ set,
32
+ reset: () => set(toValue(options.defaultValue))
33
+ };
34
+ }
35
+ //#endregion
36
+ export { useControllableState };
@@ -0,0 +1,7 @@
1
+ import { i as getButtonKeyboardAction, n as ButtonKeyboardAction, r as ButtonKeyboardPhase, t as _default } from "./button-D7sM9Xmj.mjs";
2
+ import { n as PrimitiveElement, r as _default$2, t as PrimitiveAs } from "./primitive-BtvwikH1.mjs";
3
+ import { n as CheckboxState, r as getCheckboxState, t as _default$1 } from "./checkbox-DkwZFC80.mjs";
4
+ import { i as useControllableState, n as ControllableStateOptions, r as StateUpdate, t as ControllableState } from "./controllable-state-DXsYJ3yl.mjs";
5
+ import { ComponentContext, createContext } from "./context.mjs";
6
+ import { t as _default$3 } from "./visually-hidden-BegtnMng.mjs";
7
+ export { _default as Button, ButtonKeyboardAction, ButtonKeyboardPhase, _default$1 as Checkbox, CheckboxState, ComponentContext, ControllableState, ControllableStateOptions, _default$2 as Primitive, PrimitiveAs, PrimitiveElement, StateUpdate, _default$3 as VisuallyHidden, createContext, getButtonKeyboardAction, getCheckboxState, useControllableState };
package/dist/index.mjs ADDED
@@ -0,0 +1,7 @@
1
+ import { n as getCheckboxState, t as CheckboxControl_default } from "./checkbox--QJ6FhT4.mjs";
2
+ import { useControllableState } from "./controllable-state.mjs";
3
+ import { createContext } from "./context.mjs";
4
+ import { n as getButtonKeyboardAction, t as ActionButton_default } from "./button-BcfUlpr_.mjs";
5
+ import { t as PrimitiveElement_default } from "./primitive-DJB7pOf3.mjs";
6
+ import { t as VisuallyHidden_default } from "./visually-hidden-QENRapzW.mjs";
7
+ export { ActionButton_default as Button, CheckboxControl_default as Checkbox, PrimitiveElement_default as Primitive, VisuallyHidden_default as VisuallyHidden, createContext, getButtonKeyboardAction, getCheckboxState, useControllableState };
@@ -0,0 +1,2 @@
1
+ import { n as createPDFSource, t as CreatePDFSourceOptions } from "./pdf-source-COxN3A1l.mjs";
2
+ export { type CreatePDFSourceOptions, createPDFSource };
@@ -0,0 +1,2 @@
1
+ import { t as createPDFSource } from "./pdf-source-C52YE8tp.mjs";
2
+ export { createPDFSource };
@@ -0,0 +1,28 @@
1
+ //#region src/media-source.d.ts
2
+ /** Media resource category used to constrain inline data. */
3
+ type MediaSourceKind = "audio" | "image" | "pdf" | "stream" | "track" | "video";
4
+ /** Options for {@link normalizeMediaSource}. */
5
+ interface NormalizeMediaSourceOptions {
6
+ /** Expected media resource category. */
7
+ readonly kind: MediaSourceKind;
8
+ /**
9
+ * Permits an unencrypted HTTP resource for local development.
10
+ *
11
+ * @default false
12
+ */
13
+ readonly allowInsecure?: boolean;
14
+ }
15
+ /**
16
+ * Validates and normalizes a media resource reference.
17
+ *
18
+ * Relative references, network-relative references, encrypted remote URLs,
19
+ * object URLs, and category-matched inline data are accepted. Unencrypted
20
+ * remote URLs require an explicit opt-in. Unknown and script-capable schemes
21
+ * are rejected.
22
+ *
23
+ * @throws {TypeError} When the resource is empty, malformed, unsafe, or does
24
+ * not match the requested media category.
25
+ */
26
+ declare function normalizeMediaSource(source: string, options: NormalizeMediaSourceOptions): string;
27
+ //#endregion
28
+ export { MediaSourceKind, NormalizeMediaSourceOptions, normalizeMediaSource };
@@ -0,0 +1,67 @@
1
+ //#region src/media-source.ts
2
+ const SOURCE_KINDS = new Set([
3
+ "audio",
4
+ "image",
5
+ "pdf",
6
+ "stream",
7
+ "track",
8
+ "video"
9
+ ]);
10
+ const SCHEME = /^([a-z][a-z\d+.-]*):/i;
11
+ const BASE64_PAYLOAD = /^(?:[a-z\d+/]{4})*(?:[a-z\d+/]{2}==|[a-z\d+/]{3}=)?$/i;
12
+ const BINARY_MEDIA_TYPE = /^(audio|image|video)\/([a-z\d][a-z\d.+-]*)$/i;
13
+ const INVALID_PERCENT_ESCAPE = /%(?![a-f\d]{2})/i;
14
+ /**
15
+ * Validates and normalizes a media resource reference.
16
+ *
17
+ * Relative references, network-relative references, encrypted remote URLs,
18
+ * object URLs, and category-matched inline data are accepted. Unencrypted
19
+ * remote URLs require an explicit opt-in. Unknown and script-capable schemes
20
+ * are rejected.
21
+ *
22
+ * @throws {TypeError} When the resource is empty, malformed, unsafe, or does
23
+ * not match the requested media category.
24
+ */
25
+ function normalizeMediaSource(source, options) {
26
+ const kind = options?.kind;
27
+ if (!SOURCE_KINDS.has(kind)) throw new TypeError(`[VIZE_UI_MEDIA_INVALID_KIND] Unknown media source kind: ${String(kind)}`);
28
+ if (typeof source !== "string") throw new TypeError("[VIZE_UI_MEDIA_INVALID_SOURCE] Media source must be a string");
29
+ const normalized = source.trim();
30
+ if (normalized.length === 0 || containsControlCharacter(normalized)) throw new TypeError("[VIZE_UI_MEDIA_INVALID_SOURCE] Media source must be non-empty and contain no control characters");
31
+ const scheme = SCHEME.exec(normalized)?.[1]?.toLowerCase();
32
+ if (scheme === void 0 || scheme === "https" || scheme === "blob") return normalized;
33
+ if (scheme === "http" && options.allowInsecure === true) return normalized;
34
+ if (scheme === "data" && isAllowedDataSource(normalized, kind)) return normalized;
35
+ throw new TypeError(`[VIZE_UI_MEDIA_DISALLOWED_SOURCE] Source is not allowed for ${kind}: ${scheme}`);
36
+ }
37
+ function isAllowedDataSource(source, kind) {
38
+ if (kind === "stream") return false;
39
+ const commaIndex = source.indexOf(",");
40
+ if (commaIndex < 6) return false;
41
+ const metadata = source.slice(5, commaIndex).toLowerCase();
42
+ const payload = source.slice(commaIndex + 1);
43
+ if (payload.length === 0) return false;
44
+ const segments = metadata.split(";");
45
+ const mediaType = segments.shift();
46
+ const isBase64 = segments.at(-1) === "base64";
47
+ if (isBase64) segments.pop();
48
+ if (kind === "pdf") return mediaType === "application/pdf" && segments.length === 0 && isBase64 && isValidBase64(payload);
49
+ if (kind === "track") {
50
+ const hasValidParameters = segments.length === 0 || segments.length === 1 && segments[0] === "charset=utf-8";
51
+ if (mediaType !== "text/vtt" || !hasValidParameters) return false;
52
+ return isBase64 ? isValidBase64(payload) : !INVALID_PERCENT_ESCAPE.test(payload);
53
+ }
54
+ return (mediaType === void 0 ? void 0 : BINARY_MEDIA_TYPE.exec(mediaType)?.[1])?.toLowerCase() === kind && segments.length === 0 && isBase64 && isValidBase64(payload);
55
+ }
56
+ function isValidBase64(payload) {
57
+ return payload.length > 0 && BASE64_PAYLOAD.test(payload);
58
+ }
59
+ function containsControlCharacter(value) {
60
+ for (const character of value) {
61
+ const code = character.charCodeAt(0);
62
+ if (code <= 31 || code === 127) return true;
63
+ }
64
+ return false;
65
+ }
66
+ //#endregion
67
+ export { normalizeMediaSource };
@@ -0,0 +1,3 @@
1
+ import { MediaSourceKind, NormalizeMediaSourceOptions, normalizeMediaSource } from "./media-source.mjs";
2
+ import { n as createPDFSource, t as CreatePDFSourceOptions } from "./pdf-source-COxN3A1l.mjs";
3
+ export { type CreatePDFSourceOptions, type MediaSourceKind, type NormalizeMediaSourceOptions, createPDFSource, normalizeMediaSource };
package/dist/media.mjs ADDED
@@ -0,0 +1,3 @@
1
+ import { normalizeMediaSource } from "./media-source.mjs";
2
+ import { t as createPDFSource } from "./pdf-source-C52YE8tp.mjs";
3
+ export { createPDFSource, normalizeMediaSource };
@@ -0,0 +1,23 @@
1
+ import { normalizeMediaSource } from "./media-source.mjs";
2
+ //#region src/pdf-source.ts
3
+ /**
4
+ * Validates a PDF resource and applies a standards-compatible initial page.
5
+ *
6
+ * @throws {TypeError} When the PDF source is unsafe or malformed.
7
+ * @throws {RangeError} When `page` is not a positive safe integer.
8
+ */
9
+ function createPDFSource(source, options = {}) {
10
+ const normalized = normalizeMediaSource(source, {
11
+ kind: "pdf",
12
+ allowInsecure: options.allowInsecure ?? false
13
+ });
14
+ if (options.page === void 0) return normalized;
15
+ if (!Number.isSafeInteger(options.page) || options.page < 1) throw new RangeError(`[VIZE_UI_MEDIA_INVALID_PDF_PAGE] PDF page must be a positive safe integer; received ${String(options.page)}`);
16
+ const fragmentIndex = normalized.indexOf("#");
17
+ const resource = fragmentIndex === -1 ? normalized : normalized.slice(0, fragmentIndex);
18
+ const parameters = (fragmentIndex === -1 ? "" : normalized.slice(fragmentIndex + 1)).split("&").filter((parameter) => parameter.length > 0 && !parameter.toLowerCase().startsWith("page="));
19
+ parameters.push(`page=${options.page}`);
20
+ return `${resource}#${parameters.join("&")}`;
21
+ }
22
+ //#endregion
23
+ export { createPDFSource as t };
@@ -0,0 +1,28 @@
1
+ //#region src/pdf-source.d.ts
2
+ /** Options for {@link createPDFSource}. */
3
+ interface CreatePDFSourceOptions {
4
+ /**
5
+ * One-based initial PDF page.
6
+ *
7
+ * Existing `page` parameters in the PDF fragment are replaced while other
8
+ * fragment parameters are preserved.
9
+ *
10
+ * @default undefined
11
+ */
12
+ readonly page?: number;
13
+ /**
14
+ * Permits an unencrypted HTTP resource for local development.
15
+ *
16
+ * @default false
17
+ */
18
+ readonly allowInsecure?: boolean;
19
+ }
20
+ /**
21
+ * Validates a PDF resource and applies a standards-compatible initial page.
22
+ *
23
+ * @throws {TypeError} When the PDF source is unsafe or malformed.
24
+ * @throws {RangeError} When `page` is not a positive safe integer.
25
+ */
26
+ declare function createPDFSource(source: string, options?: CreatePDFSourceOptions): string;
27
+ //#endregion
28
+ export { createPDFSource as n, CreatePDFSourceOptions as t };
@@ -0,0 +1,32 @@
1
+ import * as _$vue from "vue";
2
+ import { Component, ComponentPublicInstance } from "vue";
3
+
4
+ //#region src/PrimitiveElement.vue.d.ts
5
+ type __VLS_Props = {
6
+ /**
7
+ * Native element, custom element, or component to render.
8
+ *
9
+ * @default "div"
10
+ */
11
+ readonly as?: PrimitiveAs;
12
+ };
13
+ declare var __VLS_11: string, __VLS_12: {};
14
+ type __VLS_Slots = {} & { [K in NonNullable<typeof __VLS_11>]?: (props: typeof __VLS_12) => any };
15
+ declare const __VLS_base: _$vue.DefineComponent<__VLS_Props, {
16
+ element: Readonly<_$vue.ShallowRef<PrimitiveElement | null>>;
17
+ }, {}, {}, {}, _$vue.ComponentOptionsMixin, _$vue.ComponentOptionsMixin, {}, string, _$vue.PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, _$vue.ComponentProvideOptions, false, {}, any>;
18
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
19
+ declare const _default: typeof __VLS_export;
20
+ type __VLS_WithSlots<T, S> = T & {
21
+ new (): {
22
+ $slots: S;
23
+ };
24
+ };
25
+ //#endregion
26
+ //#region src/primitive.d.ts
27
+ /** Native element, custom element, or component accepted by {@link Primitive}. */
28
+ type PrimitiveAs = string | Component;
29
+ /** Rendered value exposed by {@link Primitive}. */
30
+ type PrimitiveElement = Element | ComponentPublicInstance;
31
+ //#endregion
32
+ export { PrimitiveElement as n, _default as r, PrimitiveAs as t };
@@ -0,0 +1,34 @@
1
+ import { t as _plugin_vue_export_helper_default } from "./_plugin-vue_export-helper-BVN2DL-U.mjs";
2
+ import { createBlock, createSlots, defineComponent, openBlock, renderList, renderSlot, resolveDynamicComponent, useSlots, useTemplateRef, withCtx } from "vue";
3
+ //#endregion
4
+ //#region src/PrimitiveElement.vue
5
+ var PrimitiveElement_default = /* @__PURE__ */ _plugin_vue_export_helper_default(/* @__PURE__ */ defineComponent({
6
+ __name: "PrimitiveElement",
7
+ props: { as: {
8
+ type: null,
9
+ required: false,
10
+ default: "div"
11
+ } },
12
+ setup(__props, { expose: __expose }) {
13
+ const slots = useSlots();
14
+ const element = useTemplateRef("element");
15
+ function getSlotNames() {
16
+ return Object.keys(slots);
17
+ }
18
+ __expose({ element });
19
+ return (_ctx, _cache) => {
20
+ return openBlock(), createBlock(resolveDynamicComponent(__props.as), {
21
+ ref_key: "element",
22
+ ref: element,
23
+ "data-vize-ui": "primitive"
24
+ }, createSlots({ _: 2 }, [renderList(getSlotNames(), (name) => {
25
+ return {
26
+ name,
27
+ fn: withCtx(() => [renderSlot(_ctx.$slots, name, {}, void 0, true)])
28
+ };
29
+ })]), 1536);
30
+ };
31
+ }
32
+ }), [["__scopeId", "data-v-6c8b649e"]]);
33
+ //#endregion
34
+ export { PrimitiveElement_default as t };
@@ -0,0 +1,2 @@
1
+ import { n as PrimitiveElement, r as _default, t as PrimitiveAs } from "./primitive-BtvwikH1.mjs";
2
+ export { _default as Primitive, PrimitiveAs, PrimitiveElement };
@@ -0,0 +1,2 @@
1
+ import { t as PrimitiveElement_default } from "./primitive-DJB7pOf3.mjs";
2
+ export { PrimitiveElement_default as Primitive };
package/dist/style.css ADDED
@@ -0,0 +1 @@
1
+ [data-vize-ui=visually-hidden][data-v-812b49c6]{clip-path:inset(50%);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}
@@ -0,0 +1,19 @@
1
+ import * as _$vue from "vue";
2
+
3
+ //#region src/VisuallyHidden.vue.d.ts
4
+ declare var __VLS_1: {};
5
+ type __VLS_Slots = {} & {
6
+ default?: (props: typeof __VLS_1) => any;
7
+ };
8
+ declare const __VLS_base: _$vue.DefineComponent<{}, {
9
+ element: Readonly<_$vue.ShallowRef<HTMLSpanElement | null>>;
10
+ }, {}, {}, {}, _$vue.ComponentOptionsMixin, _$vue.ComponentOptionsMixin, {}, string, _$vue.PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, _$vue.ComponentProvideOptions, true, {}, any>;
11
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
12
+ declare const _default: typeof __VLS_export;
13
+ type __VLS_WithSlots<T, S> = T & {
14
+ new (): {
15
+ $slots: S;
16
+ };
17
+ };
18
+ //#endregion
19
+ export { _default as t };
@@ -0,0 +1,21 @@
1
+ import './style.css';
2
+ import { t as _plugin_vue_export_helper_default } from "./_plugin-vue_export-helper-BVN2DL-U.mjs";
3
+ import { createElementBlock, defineComponent, openBlock, renderSlot, useTemplateRef } from "vue";
4
+ //#endregion
5
+ //#region src/VisuallyHidden.vue
6
+ var VisuallyHidden_default = /* @__PURE__ */ _plugin_vue_export_helper_default(/* @__PURE__ */ defineComponent({
7
+ __name: "VisuallyHidden",
8
+ setup(__props, { expose: __expose }) {
9
+ const element = useTemplateRef("element");
10
+ __expose({ element });
11
+ return (_ctx, _cache) => {
12
+ return openBlock(), createElementBlock("span", {
13
+ ref_key: "element",
14
+ ref: element,
15
+ "data-vize-ui": "visually-hidden"
16
+ }, [renderSlot(_ctx.$slots, "default", {}, void 0, true)], 512);
17
+ };
18
+ }
19
+ }), [["__scopeId", "data-v-812b49c6"]]);
20
+ //#endregion
21
+ export { VisuallyHidden_default as t };
@@ -0,0 +1,2 @@
1
+ import { t as _default } from "./visually-hidden-BegtnMng.mjs";
2
+ export { _default as VisuallyHidden };
@@ -0,0 +1,2 @@
1
+ import { t as VisuallyHidden_default } from "./visually-hidden-QENRapzW.mjs";
2
+ export { VisuallyHidden_default as VisuallyHidden };
package/package.json ADDED
@@ -0,0 +1,117 @@
1
+ {
2
+ "name": "@vizejs/ui",
3
+ "version": "0.302.0",
4
+ "description": "Accessible, headless, Native CSS-first UI primitives",
5
+ "keywords": [
6
+ "accessibility",
7
+ "headless",
8
+ "type-safe",
9
+ "vize",
10
+ "vue"
11
+ ],
12
+ "homepage": "https://github.com/ubugeeei-prod/vize",
13
+ "bugs": {
14
+ "url": "https://github.com/ubugeeei-prod/vize/issues"
15
+ },
16
+ "license": "MIT",
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "https://github.com/ubugeeei-prod/vize.git",
20
+ "directory": "npm/ui/core"
21
+ },
22
+ "files": [
23
+ "dist"
24
+ ],
25
+ "type": "module",
26
+ "sideEffects": [
27
+ "./dist/*.css"
28
+ ],
29
+ "main": "./dist/index.mjs",
30
+ "types": "./dist/index.d.mts",
31
+ "exports": {
32
+ ".": {
33
+ "types": "./dist/index.d.mts",
34
+ "import": "./dist/index.mjs",
35
+ "default": "./dist/index.mjs"
36
+ },
37
+ "./button": {
38
+ "types": "./dist/button.d.mts",
39
+ "import": "./dist/button.mjs",
40
+ "default": "./dist/button.mjs"
41
+ },
42
+ "./checkbox": {
43
+ "types": "./dist/checkbox.d.mts",
44
+ "import": "./dist/checkbox.mjs",
45
+ "default": "./dist/checkbox.mjs"
46
+ },
47
+ "./context": {
48
+ "types": "./dist/context.d.mts",
49
+ "import": "./dist/context.mjs",
50
+ "default": "./dist/context.mjs"
51
+ },
52
+ "./controllable-state": {
53
+ "types": "./dist/controllable-state.d.mts",
54
+ "import": "./dist/controllable-state.mjs",
55
+ "default": "./dist/controllable-state.mjs"
56
+ },
57
+ "./primitive": {
58
+ "types": "./dist/primitive.d.mts",
59
+ "import": "./dist/primitive.mjs",
60
+ "default": "./dist/primitive.mjs"
61
+ },
62
+ "./visually-hidden": {
63
+ "types": "./dist/visually-hidden.d.mts",
64
+ "import": "./dist/visually-hidden.mjs",
65
+ "default": "./dist/visually-hidden.mjs"
66
+ },
67
+ "./style.css": "./dist/style.css",
68
+ "./media": {
69
+ "types": "./dist/media.d.mts",
70
+ "import": "./dist/media.mjs",
71
+ "default": "./dist/media.mjs"
72
+ },
73
+ "./media/pdf": {
74
+ "types": "./dist/media-pdf.d.mts",
75
+ "import": "./dist/media-pdf.mjs",
76
+ "default": "./dist/media-pdf.mjs"
77
+ },
78
+ "./media/source": {
79
+ "types": "./dist/media-source.d.mts",
80
+ "import": "./dist/media-source.mjs",
81
+ "default": "./dist/media-source.mjs"
82
+ }
83
+ },
84
+ "publishConfig": {
85
+ "access": "public"
86
+ },
87
+ "scripts": {
88
+ "build": "vp pack",
89
+ "dev": "vp pack --watch",
90
+ "lint:sfc": "vp exec node scripts/lint-sfc.ts src",
91
+ "pretest": "vp pack && pnpm check:size",
92
+ "test": "vp test run",
93
+ "check": "vp check src scripts vite.config.ts",
94
+ "check:fix": "vp check --fix src scripts vite.config.ts",
95
+ "check:size": "node scripts/check-size.mjs",
96
+ "fmt": "vp fmt --write src scripts vite.config.ts"
97
+ },
98
+ "devDependencies": {
99
+ "@tsdown/css": "catalog:content",
100
+ "@types/node": "catalog:typescript",
101
+ "@vitejs/plugin-vue": "catalog:vite-stack",
102
+ "@vizejs/native": "workspace:*",
103
+ "@vizejs/ui-tooling": "workspace:*",
104
+ "@vue/test-utils": "catalog:vue-stable",
105
+ "happy-dom": "catalog:testing",
106
+ "typescript": "catalog:typescript",
107
+ "vite": "catalog:vite-stack",
108
+ "vite-plus": "catalog:vite-stack",
109
+ "vue": "catalog:vue-stable"
110
+ },
111
+ "peerDependencies": {
112
+ "vue": "^3.5.0"
113
+ },
114
+ "engines": {
115
+ "node": ">=24"
116
+ }
117
+ }