@ecopages/radiant-ui 0.2.2 → 0.2.3

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.
@@ -1,7 +1,8 @@
1
1
  import type { JsxCustomElementAttributes, JsxElementProps, JsxRenderable } from '@ecopages/jsx';
2
+ import type { NativeInputProps } from '@/lib/native-element-props';
2
3
  import type { RuiAutocomplete as RuiAutocompleteElement, RuiAutocompleteProps } from './autocomplete.script';
3
4
  import './autocomplete.script';
4
- export type RuiAutocompleteInputProps = JsxElementProps<HTMLInputElement> & {
5
+ export type RuiAutocompleteInputProps = NativeInputProps & {
5
6
  placeholder?: string;
6
7
  disabled?: boolean;
7
8
  };
@@ -1,4 +1,5 @@
1
1
  import type { JsxElementProps } from '@ecopages/jsx';
2
+ import type { NativeButtonProps } from '@/lib/native-element-props';
2
3
  export type RuiButtonVariant = 'filled' | 'outline' | 'destructive' | 'ghost' | 'link';
3
4
  export type RuiButtonSize = 'none' | 'sm' | 'md' | 'lg';
4
5
  type RuiButtonChrome = {
@@ -9,7 +10,7 @@ type RuiButtonChrome = {
9
10
  /** Makes a control-sized button square, for example for an icon-only action. */
10
11
  square?: boolean;
11
12
  };
12
- export type RuiButtonControlProps = JsxElementProps<HTMLButtonElement> & RuiButtonChrome & {
13
+ export type RuiButtonControlProps = NativeButtonProps & RuiButtonChrome & {
13
14
  /** Native button type. Default: `button`. */
14
15
  type?: 'button' | 'submit' | 'reset';
15
16
  /** Disabled state. */
@@ -34,7 +35,8 @@ export type RuiButtonProps = RuiButtonControlProps | RuiButtonLinkProps;
34
35
  * Presentational wrapper around a native `<button>` or button-styled `<a>`.
35
36
  *
36
37
  * No custom element and no controller — only CSS variants/sizes. The `href`
37
- * union branch preserves native link semantics for navigation.
38
+ * union branch preserves native link semantics for navigation. Native button
39
+ * attributes such as `name` and `value` type-check on the control branch.
38
40
  *
39
41
  * @remarks
40
42
  * Default/`md` height uses `--size-control-md`, the same token as `RuiInput`, so
@@ -1,4 +1,5 @@
1
1
  import { type JsxCustomElementAttributes, type JsxElementProps, type JsxRenderable } from '@ecopages/jsx';
2
+ import type { NativeButtonProps } from '@/lib/native-element-props';
2
3
  import { type RuiCarousel as RuiCarouselElement, type RuiCarouselProps } from './carousel.script';
3
4
  import './carousel.script';
4
5
  export type RuiCarouselSlideData = {
@@ -16,7 +17,7 @@ export type RuiCarouselSlideProps = Omit<JsxElementProps<HTMLDivElement>, 'id'>
16
17
  * @remarks Stamps `[data-slide]` with the slide `id`.
17
18
  */
18
19
  export declare function RuiCarouselSlide({ id, children, class: className, ...props }: RuiCarouselSlideProps): JsxRenderable;
19
- export type RuiCarouselControlProps = JsxElementProps<HTMLButtonElement> & {
20
+ export type RuiCarouselControlProps = NativeButtonProps & {
20
21
  disabled?: boolean;
21
22
  /** Match `controls-variant="overlay"` on the carousel for circular on-slide chrome. */
22
23
  overlay?: boolean;
@@ -31,7 +32,7 @@ export type RuiCarouselControlProps = JsxElementProps<HTMLButtonElement> & {
31
32
  export declare function RuiCarouselPrev({ children, class: className, disabled, overlay, aria, ...props }: RuiCarouselControlProps): JsxRenderable;
32
33
  /** Next carousel control. Stamps `[data-carousel-action="next"]` and `data-ref="next"`. */
33
34
  export declare function RuiCarouselNext({ children, class: className, disabled, overlay, aria, ...props }: RuiCarouselControlProps): JsxRenderable;
34
- export type RuiCarouselRotationProps = JsxElementProps<HTMLButtonElement> & {
35
+ export type RuiCarouselRotationProps = NativeButtonProps & {
35
36
  overlay?: boolean;
36
37
  };
37
38
  /** Play/pause rotation control. Stamps `[data-carousel-action="rotation"]` and `data-ref="rotation"`. */
@@ -1,4 +1,5 @@
1
1
  import type { JsxCustomElementAttributes, JsxElementProps, JsxRenderable } from '@ecopages/jsx';
2
+ import type { NativeButtonProps, NativeInputProps } from '@/lib/native-element-props';
2
3
  import { type RuiListboxOptionData } from '../listbox';
3
4
  import type { RuiCombobox as RuiComboboxElement, RuiComboboxProps } from './combobox.script';
4
5
  import './combobox.script';
@@ -8,7 +9,7 @@ export type RuiComboboxControlProps = JsxElementProps<HTMLDivElement>;
8
9
  * @cssclass rui-combobox__control - Bordered control-height row.
9
10
  */
10
11
  export declare function RuiComboboxControl({ children, class: className, ...props }: RuiComboboxControlProps): JsxRenderable;
11
- export type RuiComboboxInputProps = JsxElementProps<HTMLInputElement> & {
12
+ export type RuiComboboxInputProps = NativeInputProps & {
12
13
  placeholder?: string;
13
14
  disabled?: boolean;
14
15
  };
@@ -17,12 +18,12 @@ export type RuiComboboxInputProps = JsxElementProps<HTMLInputElement> & {
17
18
  * @cssclass rui-combobox__input - Combobox text input.
18
19
  */
19
20
  export declare function RuiComboboxInput({ placeholder, disabled, class: className, ...props }: RuiComboboxInputProps): JsxRenderable;
20
- export type RuiComboboxTriggerProps = JsxElementProps<HTMLButtonElement> & {
21
+ export type RuiComboboxTriggerProps = NativeButtonProps & {
21
22
  disabled?: boolean;
22
23
  };
23
24
  /** Toggle button for opening the listbox popup. Stamps `[data-combobox-trigger]`. Children replace the default chevron icon. */
24
25
  export declare function RuiComboboxTrigger({ children, class: className, aria, disabled, ...props }: RuiComboboxTriggerProps): JsxRenderable;
25
- export type RuiComboboxClearProps = JsxElementProps<HTMLButtonElement> & {
26
+ export type RuiComboboxClearProps = NativeButtonProps & {
26
27
  disabled?: boolean;
27
28
  };
28
29
  /** Clears the current selection. Stamps `[data-combobox-clear]`. Place next to `RuiComboboxTrigger`. Children replace the default close icon. */
@@ -1,4 +1,5 @@
1
1
  import type { JsxCustomElementAttributes, JsxElementProps } from '@ecopages/jsx';
2
+ import type { NativeButtonProps } from '@/lib/native-element-props';
2
3
  import type { RuiCycleToggle as RuiCycleToggleElement, RuiCycleToggleProps } from './cycle-toggle.script';
3
4
  import './cycle-toggle.script';
4
5
  export type RuiCycleToggleItemProps = Omit<JsxElementProps<HTMLSpanElement>, 'id'> & {
@@ -7,7 +8,7 @@ export type RuiCycleToggleItemProps = Omit<JsxElementProps<HTMLSpanElement>, 'id
7
8
  /** Whether this item is selected in the initial document. */
8
9
  selected?: boolean;
9
10
  };
10
- export type RuiCycleToggleButtonProps = JsxElementProps<HTMLButtonElement> & Pick<RuiCycleToggleProps, 'disabled' | 'label' | 'size' | 'variant'>;
11
+ export type RuiCycleToggleButtonProps = NativeButtonProps & Pick<RuiCycleToggleProps, 'disabled' | 'label' | 'size' | 'variant'>;
11
12
  /**
12
13
  * One cycle option inside the button. Stamps `[data-cycle-value]` from `id`.
13
14
  *
@@ -1,4 +1,5 @@
1
1
  import type { JsxCustomElementAttributes, JsxElementProps } from '@ecopages/jsx';
2
+ import type { NativeButtonProps } from '@/lib/native-element-props';
2
3
  import { type RuiCalendarElement, type RuiCalendarProps } from '../calendar';
3
4
  import { type RuiDateInputElement, type RuiDateInputProps } from '../date-input';
4
5
  import type { RuiDateField as RuiDateFieldElement, RuiDateFieldProps } from './date-field.script';
@@ -10,7 +11,7 @@ export declare function RuiDateFieldControl({ children, class: className, ...pro
10
11
  export type RuiDateFieldInputProps = JsxCustomElementAttributes<RuiDateInputElement, RuiDateInputProps>;
11
12
  /** Nested `rui-date-input`. Stamps `[data-date-field-input]`. */
12
13
  export declare function RuiDateFieldInput({ class: className, ...props }: RuiDateFieldInputProps): import("@ecopages/jsx").JsxRenderable;
13
- export type RuiDateFieldToggleProps = JsxElementProps<HTMLButtonElement>;
14
+ export type RuiDateFieldToggleProps = NativeButtonProps;
14
15
  /** Calendar toggle. Stamps `[data-date-field-trigger]` and `data-ref="trigger"`. */
15
16
  export declare function RuiDateFieldToggle({ children, class: className, aria, ...props }: RuiDateFieldToggleProps): import("@ecopages/jsx").JsxRenderable;
16
17
  export type RuiDateFieldPopoverProps = JsxElementProps<HTMLDivElement>;
@@ -1,4 +1,5 @@
1
1
  import type { JsxCustomElementAttributes, JsxElementProps } from '@ecopages/jsx';
2
+ import type { NativeButtonProps } from '@/lib/native-element-props';
2
3
  import { type RuiCalendarElement, type RuiCalendarProps } from '../calendar';
3
4
  import { type RuiDateInputElement, type RuiDateInputProps } from '../date-input';
4
5
  import type { RuiDateRangePicker as RuiDateRangePickerElement, RuiDateRangePickerProps } from './date-range-picker.script';
@@ -19,7 +20,7 @@ export declare function RuiDateRangePickerEndInput({ class: className, ...props
19
20
  export type RuiDateRangePickerSeparatorProps = JsxElementProps<HTMLSpanElement>;
20
21
  /** Visual separator between the start and end inputs. */
21
22
  export declare function RuiDateRangePickerSeparator({ children, class: className, ...props }: RuiDateRangePickerSeparatorProps): import("@ecopages/jsx").JsxRenderable;
22
- export type RuiDateRangePickerToggleProps = JsxElementProps<HTMLButtonElement>;
23
+ export type RuiDateRangePickerToggleProps = NativeButtonProps;
23
24
  /** Calendar toggle. Stamps `[data-range-trigger]` and `data-ref="trigger"`. */
24
25
  export declare function RuiDateRangePickerToggle({ children, class: className, aria, ...props }: RuiDateRangePickerToggleProps): import("@ecopages/jsx").JsxRenderable;
25
26
  export type RuiDateRangePickerPopoverProps = JsxElementProps<HTMLDivElement>;
@@ -1,4 +1,5 @@
1
1
  import { type JsxCustomElementAttributes, type JsxElementProps, type JsxRenderable } from '@ecopages/jsx';
2
+ import type { NativeButtonProps } from '@/lib/native-element-props';
2
3
  import type { RuiDialog as RuiDialogElement, RuiDialogProps } from './dialog.script';
3
4
  import './dialog.script';
4
5
  export type RuiDialogTitleProps = JsxElementProps<HTMLDivElement>;
@@ -26,7 +27,7 @@ export type RuiDialogActionsProps = JsxElementProps<HTMLDivElement>;
26
27
  * @cssclass rui-dialog__actions - Right-aligned action row.
27
28
  */
28
29
  export declare function RuiDialogActions({ children, class: className, ...props }: RuiDialogActionsProps): JsxRenderable;
29
- export type RuiDialogCloseProps = JsxElementProps<HTMLButtonElement>;
30
+ export type RuiDialogCloseProps = NativeButtonProps;
30
31
  /**
31
32
  * Close control for the dialog surface.
32
33
  *
@@ -1,4 +1,5 @@
1
1
  import type { JsxCustomElementAttributes, JsxElementProps, JsxRenderable } from '@ecopages/jsx';
2
+ import type { NativeButtonProps } from '@/lib/native-element-props';
2
3
  import type { RuiDisclosureGroup as RuiDisclosureGroupElement, RuiDisclosureGroupProps } from './disclosure-group.script';
3
4
  import './disclosure-group.script';
4
5
  import type { RuiDisclosure as RuiDisclosureElement, RuiDisclosureProps } from './disclosure.script';
@@ -14,7 +15,7 @@ export type RuiDisclosureIconProps = JsxElementProps<HTMLSpanElement> & {
14
15
  * @cssclass rui-disclosure__icon--plus - Toggles between `+` and `×`.
15
16
  */
16
17
  export declare function RuiDisclosureIcon({ variant, class: className, children, ...props }: RuiDisclosureIconProps): JsxRenderable;
17
- export type RuiDisclosureTriggerProps = JsxElementProps<HTMLButtonElement> & {
18
+ export type RuiDisclosureTriggerProps = NativeButtonProps & {
18
19
  disabled?: boolean;
19
20
  icon?: JsxRenderable | null;
20
21
  iconPosition?: 'start' | 'end';
@@ -1,5 +1,5 @@
1
- import type { JsxElementProps } from '@ecopages/jsx';
2
- export type RuiInputProps = JsxElementProps<HTMLInputElement> & {
1
+ import type { NativeInputProps } from '@/lib/native-element-props';
2
+ export type RuiInputProps = NativeInputProps & {
3
3
  value?: string;
4
4
  type?: string;
5
5
  placeholder?: string;
@@ -18,6 +18,7 @@ export type RuiInputProps = JsxElementProps<HTMLInputElement> & {
18
18
  *
19
19
  * Pass `mask` to guide entry with an [IMask](https://imask.js.org/guide.html#masked-pattern) pattern.
20
20
  * No custom element — Field owns labeling, `aria-*`, and validation wiring.
21
+ * Native `<input>` attributes (`required`, `autocomplete`, `pattern`, …) are part of the props type.
21
22
  *
22
23
  * @remarks
23
24
  * Sets `data-rui-control` for `RuiField` discovery. Height uses `--size-control-md`
@@ -1,2 +1,2 @@
1
- import{jsx as x}from"@ecopages/jsx/jsx-runtime";function u(...e){return e.filter(Boolean).join(" ")}function o(e){return e?c(e.split(",")):[]}function g(e){return e.join(",")}var s={fromAttribute:e=>o(e),toAttribute:e=>e.length>0?g(e):null,fromProperty:e=>Array.isArray(e)?c(e.map(String)):typeof e=="string"?o(e):[]};function a(e){return e?e.split(",").map(t=>Number(t.trim())).filter(t=>Number.isFinite(t)):[]}function h(e){return e.join(",")}var l={fromAttribute:e=>a(e),toAttribute:e=>e.length>0?h(e):null,fromProperty:e=>Array.isArray(e)?e.map(Number).filter(t=>Number.isFinite(t)):typeof e=="number"&&Number.isFinite(e)?[e]:typeof e=="string"?a(e):[]};function c(e){return[...new Set(e.map(t=>t.trim()).filter(Boolean))]}var m="data-rui-field-label";var n={read:e=>{let t=Reflect.get(e,"value");return typeof t=="string"?t:e.getAttribute("value")??""},write:(e,t)=>{let r=t==null?"":String(t);e.setAttribute("value",r),"value"in e&&Reflect.set(e,"value",r)}},f={read:e=>{let t=Reflect.get(e,"value");if(typeof t=="number")return t;let r=e.getAttribute("value");return r==null||r===""?"":Number(r)},write:(e,t)=>{let r=t==null?"":String(t);e.setAttribute("value",r),"value"in e&&Reflect.set(e,"value",t)}},d={read:e=>e.querySelector('input[type="checkbox"]')?.checked??e.hasAttribute("checked"),write:(e,t)=>{t?e.setAttribute("checked",""):e.removeAttribute("checked")}};function p(e,t){let r=Reflect.get(e,"value");return r!==void 0&&t.fromProperty?t.fromProperty(r):t.fromAttribute?t.fromAttribute(e.getAttribute("value")):r}function A(e,t){Reflect.set(e,"value",t)}var i={read:e=>p(e,s),write:A},y={read:e=>p(e,l),write:A},_=new Map([["rui-checkbox",d],["rui-switch",d],["rui-combobox",{...i,submission:"none"}],["rui-date-field",n],["rui-date-input",{...n,submission:"host"}],["rui-date-range-picker",n],["rui-select",{...i,submission:"none"}],["rui-radio-group",n],["rui-checkbox-group",i],["rui-listbox",i],["rui-tag-group",i],["rui-slider",{...y,submission:"host"}],["rui-knob",{...f,submission:"host"}],["rui-number-field",{...f,submission:"host"}]]);function R({children:e,htmlFor:t,class:r,...b}){return x("label",{...b,[m]:"",class:u("rui-label",r),htmlFor:t,children:e})}export{R as RuiLabel};
1
+ import{jsx as x}from"@ecopages/jsx/jsx-runtime";function u(...e){return e.filter(Boolean).join(" ")}function o(e){return e?f(e.split(",")):[]}function g(e){return e.join(",")}var s={fromAttribute:e=>o(e),toAttribute:e=>e.length>0?g(e):null,fromProperty:e=>Array.isArray(e)?f(e.map(String)):typeof e=="string"?o(e):[]};function a(e){return e?e.split(",").map(t=>Number(t.trim())).filter(t=>Number.isFinite(t)):[]}function h(e){return e.join(",")}var l={fromAttribute:e=>a(e),toAttribute:e=>e.length>0?h(e):null,fromProperty:e=>Array.isArray(e)?e.map(Number).filter(t=>Number.isFinite(t)):typeof e=="number"&&Number.isFinite(e)?[e]:typeof e=="string"?a(e):[]};function f(e){return[...new Set(e.map(t=>t.trim()).filter(Boolean))]}var m="data-rui-field-label";var n={read:e=>{let t=Reflect.get(e,"value");return typeof t=="string"?t:e.getAttribute("value")??""},write:(e,t)=>{let r=t==null?"":String(t);e.setAttribute("value",r),"value"in e&&Reflect.set(e,"value",r)}},c={read:e=>{let t=Reflect.get(e,"value");if(typeof t=="number")return t;let r=e.getAttribute("value");return r==null||r===""?"":Number(r)},write:(e,t)=>{let r=t==null?"":String(t);e.setAttribute("value",r),"value"in e&&Reflect.set(e,"value",t)}},d={read:e=>e.querySelector('input[type="checkbox"]')?.checked??e.hasAttribute("checked"),write:(e,t)=>{t?e.setAttribute("checked",""):e.removeAttribute("checked")}};function p(e,t){let r=Reflect.get(e,"value");return r!==void 0&&t.fromProperty?t.fromProperty(r):t.fromAttribute?t.fromAttribute(e.getAttribute("value")):r}function A(e,t){Reflect.set(e,"value",t)}var i={read:e=>p(e,s),write:A},y={read:e=>p(e,l),write:A},_=new Map([["rui-checkbox",d],["rui-switch",d],["rui-combobox",{...i,submission:"none"}],["rui-date-field",n],["rui-date-input",{...n,submission:"host"}],["rui-date-range-picker",n],["rui-select",{...i,submission:"none"}],["rui-radio-group",n],["rui-checkbox-group",i],["rui-listbox",i],["rui-tag-group",i],["rui-slider",{...y,submission:"host"}],["rui-knob",{...c,submission:"host"}],["rui-number-field",{...c,submission:"host"}]]);function R({children:e,htmlFor:t,class:r,...b}){return x("label",{...b,[m]:"",class:u("rui-label",r),for:t,children:e})}export{R as RuiLabel};
2
2
  //# sourceMappingURL=index.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/components/ui/label/label.tsx", "../../../../src/lib/cx.ts", "../../../../src/components/ui/shared/multi-value.ts", "../../../../src/components/ui/form/control-protocol.ts"],
4
- "sourcesContent": ["import { jsx } from \"@ecopages/jsx/jsx-runtime\";\nimport { cx } from \"@/lib/cx\";\nimport { RUI_FIELD_LABEL_ATTR } from \"../form/control-protocol\";\nexport function RuiLabel({\n children,\n htmlFor,\n class: className,\n ...props\n}) {\n return /* @__PURE__ */jsx(\"label\", {\n ...props,\n ...{\n [RUI_FIELD_LABEL_ATTR]: \"\"\n },\n class: cx(\"rui-label\", className),\n htmlFor,\n children\n });\n}", "export function cx(...parts) {\n return parts.filter(Boolean).join(\" \");\n}", "export function parseMultiValue(value) {\n if (!value) {\n return [];\n }\n return uniqueTrimmed(value.split(\",\"));\n}\nexport function serializeMultiValue(values) {\n return values.join(\",\");\n}\nexport const multiValueTransform = {\n fromAttribute: value => parseMultiValue(value),\n toAttribute: values => values.length > 0 ? serializeMultiValue(values) : null,\n fromProperty: value => {\n if (Array.isArray(value)) {\n return uniqueTrimmed(value.map(String));\n }\n if (typeof value === \"string\") {\n return parseMultiValue(value);\n }\n return [];\n }\n};\nexport const multiValuePropOptions = {\n type: Array,\n reflect: true,\n transform: multiValueTransform\n};\nexport function parseViewValue(value) {\n return multiValueTransform.fromProperty?.(value) ?? [];\n}\nfunction parseNumberArray(value) {\n if (!value) {\n return [];\n }\n return value.split(\",\").map(item => Number(item.trim())).filter(item => Number.isFinite(item));\n}\nfunction serializeNumberArray(values) {\n return values.join(\",\");\n}\nexport const numberArrayTransform = {\n fromAttribute: value => parseNumberArray(value),\n toAttribute: values => values.length > 0 ? serializeNumberArray(values) : null,\n fromProperty: value => {\n if (Array.isArray(value)) {\n return value.map(Number).filter(item => Number.isFinite(item));\n }\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return [value];\n }\n if (typeof value === \"string\") {\n return parseNumberArray(value);\n }\n return [];\n }\n};\nfunction uniqueTrimmed(values) {\n return [...new Set(values.map(item => item.trim()).filter(Boolean))];\n}", "import { multiValueTransform, numberArrayTransform } from \"../shared/multi-value\";\nexport const RUI_CONTROL_ATTR = \"data-rui-control\";\nexport const RUI_FIELD_MANAGED_ATTR = \"data-rui-field-managed\";\nexport const RUI_FIELD_LABEL_ATTR = \"data-rui-field-label\";\nexport const RUI_FIELD_DESCRIPTION_ATTR = \"data-rui-field-description\";\nexport const RUI_FIELD_ERROR_ATTR = \"data-rui-field-error\";\nexport const RUI_FIELD_DEFAULT_VALUE_ATTR = \"data-default-value\";\nexport const RUI_FORM_DEFAULT_VALUES_ATTR = \"data-default-values\";\nexport const RUI_ARIA_TARGET_ATTR = \"data-rui-aria-target\";\nexport const RUI_ARIA_TARGETS_ATTR = \"data-rui-aria-targets\";\nconst FIELD_COLUMN_SELECTOR = '[data-ref=\"field\"]';\nfunction fieldControlSelector() {\n return `[${RUI_CONTROL_ATTR}], ${hostControlSelector()}`;\n}\nfunction hostControlSelector() {\n return Array.from(CONTROL_VALUE_ADAPTERS.keys()).join(\", \");\n}\nfunction isEmbeddedListbox(node) {\n return node.localName === \"rui-listbox\" && (node.hasAttribute(\"embedded\") || Reflect.get(node, \"embedded\") === true);\n}\nconst ARIA_TARGET_SELECTORS = {\n \"rui-combobox\": \"[data-combobox-input]\",\n \"rui-select\": \"[data-select-trigger]\",\n \"rui-tag-group\": \"[data-tag-list]\",\n \"rui-number-field\": \"[data-number-field-input], input\",\n \"rui-knob\": \"[data-knob-control]\",\n \"rui-checkbox\": \"input\",\n \"rui-checkbox-group\": \"[data-checkbox-group-root]\",\n \"rui-switch\": \"input\"\n};\nexport function isNativeTextControl(node) {\n return node.localName === \"input\" || node.localName === \"textarea\";\n}\nfunction isNativeInput(node) {\n return node.localName === \"input\";\n}\nfunction isNativeTextarea(node) {\n return node.localName === \"textarea\";\n}\nexport function isFormAssociatedHost(host) {\n return Reflect.get(host.constructor, \"formAssociated\") === true;\n}\nconst stringValueAdapter = {\n read: host => {\n const value = Reflect.get(host, \"value\");\n return typeof value === \"string\" ? value : host.getAttribute(\"value\") ?? \"\";\n },\n write: (host, value) => {\n const next = value == null ? \"\" : String(value);\n host.setAttribute(\"value\", next);\n if (\"value\" in host) {\n Reflect.set(host, \"value\", next);\n }\n }\n};\nconst numberValueAdapter = {\n read: host => {\n const value = Reflect.get(host, \"value\");\n if (typeof value === \"number\") {\n return value;\n }\n const raw = host.getAttribute(\"value\");\n return raw == null || raw === \"\" ? \"\" : Number(raw);\n },\n write: (host, value) => {\n const next = value == null ? \"\" : String(value);\n host.setAttribute(\"value\", next);\n if (\"value\" in host) {\n Reflect.set(host, \"value\", value);\n }\n }\n};\nconst booleanValueAdapter = {\n read: host => {\n const input = host.querySelector('input[type=\"checkbox\"]');\n return input?.checked ?? host.hasAttribute(\"checked\");\n },\n write: (host, value) => {\n if (value) {\n host.setAttribute(\"checked\", \"\");\n } else {\n host.removeAttribute(\"checked\");\n }\n }\n};\nfunction readHostValue(host, transform) {\n const value = Reflect.get(host, \"value\");\n if (value !== void 0 && transform.fromProperty) {\n return transform.fromProperty(value);\n }\n if (transform.fromAttribute) {\n return transform.fromAttribute(host.getAttribute(\"value\"));\n }\n return value;\n}\nfunction writeHostValue(host, value) {\n Reflect.set(host, \"value\", value);\n}\nconst stringArrayValueAdapter = {\n read: host => readHostValue(host, multiValueTransform),\n write: writeHostValue\n};\nconst sliderValueAdapter = {\n read: host => readHostValue(host, numberArrayTransform),\n write: writeHostValue\n};\nconst CONTROL_VALUE_ADAPTERS = /* @__PURE__ */new Map([[\"rui-checkbox\", booleanValueAdapter], [\"rui-switch\", booleanValueAdapter], [\"rui-combobox\", {\n ...stringArrayValueAdapter,\n submission: \"none\"\n}], [\"rui-date-field\", stringValueAdapter], [\"rui-date-input\", {\n ...stringValueAdapter,\n submission: \"host\"\n}], [\"rui-date-range-picker\", stringValueAdapter], [\"rui-select\", {\n ...stringArrayValueAdapter,\n submission: \"none\"\n}], [\"rui-radio-group\", stringValueAdapter], [\"rui-checkbox-group\", stringArrayValueAdapter], [\"rui-listbox\", stringArrayValueAdapter], [\"rui-tag-group\", stringArrayValueAdapter], [\"rui-slider\", {\n ...sliderValueAdapter,\n submission: \"host\"\n}], [\"rui-knob\", {\n ...numberValueAdapter,\n submission: \"host\"\n}], [\"rui-number-field\", {\n ...numberValueAdapter,\n submission: \"host\"\n}]]);\nfunction forEachFieldContentNode(root, visit) {\n const slotHost = root;\n const visited = /* @__PURE__ */new Set();\n const safeVisit = node => {\n if (visited.has(node)) {\n return;\n }\n visited.add(node);\n visit(node);\n };\n if (typeof slotHost.getSlotElements === \"function\") {\n for (const node of slotHost.getSlotElements()) {\n safeVisit(node);\n }\n }\n const renderRoot = root.querySelector(FIELD_COLUMN_SELECTOR) ?? root;\n for (const child of Array.from(renderRoot.children)) {\n safeVisit(child);\n }\n for (const node of renderRoot.querySelectorAll(\"*\")) {\n safeVisit(node);\n }\n for (const child of Array.from(root.children)) {\n safeVisit(child);\n }\n const shadow = root.shadowRoot;\n if (shadow) {\n for (const child of Array.from(shadow.children)) {\n safeVisit(child);\n }\n }\n}\nfunction queryFieldContent(root, selector) {\n let found = null;\n forEachFieldContentNode(root, node => {\n if (found || !(node instanceof HTMLElement)) {\n return;\n }\n if (node.matches(selector)) {\n found = node;\n return;\n }\n found = node.querySelector(selector);\n });\n return found;\n}\nfunction pickPrimaryFieldControl(candidates) {\n const eligibleCandidates = candidates.filter(candidate => !isEmbeddedListbox(candidate));\n if (eligibleCandidates.length === 0) {\n return null;\n }\n return eligibleCandidates.find(candidate => !eligibleCandidates.some(ancestor => ancestor !== candidate && ancestor.contains(candidate))) ?? null;\n}\nfunction collectFieldControls(root) {\n const candidates = [];\n forEachFieldContentNode(root, node => {\n if (node instanceof HTMLElement && node.matches(fieldControlSelector())) {\n candidates.push(node);\n }\n });\n return candidates;\n}\nfunction listFieldControlsInRenderTree(root) {\n const renderRoot = root.querySelector(FIELD_COLUMN_SELECTOR);\n if (!(renderRoot instanceof HTMLElement)) {\n return [];\n }\n return Array.from(renderRoot.querySelectorAll(fieldControlSelector())).filter(el => root.contains(el));\n}\nexport function findFieldControl(root) {\n const fromRenderTree = pickPrimaryFieldControl(listFieldControlsInRenderTree(root));\n if (fromRenderTree) {\n return fromRenderTree;\n }\n return pickPrimaryFieldControl(collectFieldControls(root));\n}\nexport function registerFieldControl(tagName, adapter) {\n const tag = tagName.toLowerCase();\n CONTROL_VALUE_ADAPTERS.set(tag, adapter);\n}\nexport function isPrimaryFieldControlEvent(root, event) {\n const control = findFieldControl(root);\n if (!control || !(event.target instanceof Element)) {\n return false;\n }\n if (event.target !== control && !control.contains(event.target)) {\n return false;\n }\n const nestedHost = event.target.closest(hostControlSelector());\n return nestedHost === control || nestedHost == null;\n}\nexport function readControlValue(control) {\n if (isNativeInput(control)) {\n const host2 = resolveControlHost(control);\n const adapter = host2 === control ? void 0 : CONTROL_VALUE_ADAPTERS.get(host2.localName);\n if (adapter) {\n return adapter.read(host2);\n }\n if (control.type === \"checkbox\") {\n return control.checked;\n }\n if (control.type === \"number\" || control.type === \"range\") {\n return control.value === \"\" ? \"\" : Number(control.value);\n }\n return control.value;\n }\n if (isNativeTextarea(control)) {\n return control.value;\n }\n const host = resolveControlHost(control);\n return CONTROL_VALUE_ADAPTERS.get(host.localName)?.read(host) ?? host.getAttribute(\"value\") ?? \"\";\n}\nexport function writeControlValue(control, value) {\n if (isNativeInput(control)) {\n const host2 = resolveControlHost(control);\n const adapter = host2 === control ? void 0 : CONTROL_VALUE_ADAPTERS.get(host2.localName);\n if (adapter) {\n adapter.write(host2, value);\n return;\n }\n if (control.type === \"checkbox\") {\n control.checked = Boolean(value);\n const ce = control.closest(\"rui-checkbox, rui-switch\");\n if (ce) {\n if (value) {\n ce.setAttribute(\"checked\", \"\");\n } else {\n ce.removeAttribute(\"checked\");\n }\n }\n return;\n }\n control.value = value == null ? \"\" : String(value);\n return;\n }\n if (isNativeTextarea(control)) {\n control.value = value == null ? \"\" : String(value);\n return;\n }\n const host = resolveControlHost(control);\n CONTROL_VALUE_ADAPTERS.get(host.localName)?.write(host, value);\n}\nfunction resolveControlHost(control) {\n if (control.hasAttribute(RUI_CONTROL_ATTR)) {\n const host = control.closest(hostControlSelector());\n return host ?? control;\n }\n return control;\n}\nexport function findFieldLabel(root) {\n return queryFieldContent(root, `[${RUI_FIELD_LABEL_ATTR}]`);\n}\nexport function findFieldDescription(root) {\n return queryFieldContent(root, `[${RUI_FIELD_DESCRIPTION_ATTR}]`);\n}\nexport function findFieldError(root) {\n const all = findFieldErrorElements(root);\n return all[0] ?? null;\n}\nexport function findFieldErrorElements(root) {\n const renderRoot = root.querySelector(FIELD_COLUMN_SELECTOR);\n if (renderRoot instanceof HTMLElement) {\n const inRender = Array.from(renderRoot.querySelectorAll(`[${RUI_FIELD_ERROR_ATTR}]`));\n if (inRender.length > 0) {\n return inRender;\n }\n }\n const fromDom = Array.from(root.querySelectorAll(`[${RUI_FIELD_ERROR_ATTR}]`));\n if (fromDom.length > 0) {\n return fromDom;\n }\n const single = queryFieldContent(root, `[${RUI_FIELD_ERROR_ATTR}]`);\n return single ? [single] : [];\n}\nexport function wireFieldControlName(controlHost, ariaTarget, name) {\n if (ariaTarget && isNativeTextControl(ariaTarget)) {\n const submission = controlHost && CONTROL_VALUE_ADAPTERS.get(controlHost.localName)?.submission;\n const namesInner = controlHost == null || controlHost === ariaTarget || !isFormAssociatedHost(controlHost) && submission !== \"host\" && submission !== \"none\";\n if (namesInner && name) {\n ariaTarget.name = name;\n } else {\n ariaTarget.removeAttribute(\"name\");\n }\n }\n if (controlHost && CONTROL_VALUE_ADAPTERS.has(controlHost.localName)) {\n Reflect.set(controlHost, \"name\", name);\n if (name) controlHost.setAttribute(\"name\", name);else controlHost.removeAttribute(\"name\");\n }\n}\nfunction isChecked(input) {\n const checked = Reflect.get(input, \"checked\");\n return typeof checked === \"boolean\" ? checked : input.hasAttribute(\"checked\");\n}\nfunction resolveDeclaredAriaTarget(control) {\n const multi = control.getAttribute(RUI_ARIA_TARGETS_ATTR);\n if (multi) {\n const firstSelector = multi.split(\",\")[0]?.trim();\n if (firstSelector) {\n return control.querySelector(firstSelector);\n }\n }\n const single = control.getAttribute(RUI_ARIA_TARGET_ATTR);\n if (single) {\n return control.querySelector(single);\n }\n return null;\n}\nfunction resolveDeclaredAriaTargets(control) {\n const multi = control.getAttribute(RUI_ARIA_TARGETS_ATTR);\n if (multi) {\n return multi.split(\",\").map(selector => selector.trim()).filter(selector => selector !== \"\").map(selector => control.querySelector(selector)).filter(node => node != null);\n }\n const single = control.getAttribute(RUI_ARIA_TARGET_ATTR);\n if (single) {\n const target = control.querySelector(single);\n return target ? [target] : [];\n }\n return [];\n}\nexport function getAriaControlTarget(control) {\n if (isNativeTextControl(control)) {\n return control;\n }\n const declared = resolveDeclaredAriaTarget(control);\n if (declared) {\n return declared;\n }\n if (control.hasAttribute(RUI_CONTROL_ATTR)) {\n return control;\n }\n if (control.localName === \"rui-slider\") {\n const thumb = Array.from(control.querySelectorAll(\"[data-thumb]\")).find(node => !node.hasAttribute(\"hidden\"));\n return thumb ?? control;\n }\n const marked = control.querySelector(`[${RUI_CONTROL_ATTR}]`);\n if (marked) {\n return marked;\n }\n if (control.localName === \"rui-radio-group\") {\n return getSelectedRadio(control) ?? control;\n }\n const selector = ARIA_TARGET_SELECTORS[control.localName];\n return selector ? control.querySelector(selector) ?? control : control;\n}\nfunction getSelectedRadio(control) {\n const radios = control.querySelectorAll('input[type=\"radio\"]');\n return Array.from(radios).find(isChecked) ?? radios[0];\n}\nexport function getAriaControlTargets(control) {\n const declared = resolveDeclaredAriaTargets(control);\n if (declared.length > 0) {\n return declared;\n }\n if (control.localName === \"rui-slider\") {\n const thumbs = Array.from(control.querySelectorAll(\"[data-thumb]\")).filter(node => !node.hasAttribute(\"hidden\"));\n return thumbs.length > 0 ? thumbs : [control];\n }\n return [getAriaControlTarget(control)];\n}"],
5
- "mappings": "AAAA,OAAS,OAAAA,MAAW,4BCAb,SAASC,KAAMC,EAAO,CAC3B,OAAOA,EAAM,OAAO,OAAO,EAAE,KAAK,GAAG,CACvC,CCFO,SAASC,EAAgBC,EAAO,CACrC,OAAKA,EAGEC,EAAcD,EAAM,MAAM,GAAG,CAAC,EAF5B,CAAC,CAGZ,CACO,SAASE,EAAoBC,EAAQ,CAC1C,OAAOA,EAAO,KAAK,GAAG,CACxB,CACO,IAAMC,EAAsB,CACjC,cAAeJ,GAASD,EAAgBC,CAAK,EAC7C,YAAaG,GAAUA,EAAO,OAAS,EAAID,EAAoBC,CAAM,EAAI,KACzE,aAAcH,GACR,MAAM,QAAQA,CAAK,EACdC,EAAcD,EAAM,IAAI,MAAM,CAAC,EAEpC,OAAOA,GAAU,SACZD,EAAgBC,CAAK,EAEvB,CAAC,CAEZ,EASA,SAASK,EAAiBC,EAAO,CAC/B,OAAKA,EAGEA,EAAM,MAAM,GAAG,EAAE,IAAIC,GAAQ,OAAOA,EAAK,KAAK,CAAC,CAAC,EAAE,OAAOA,GAAQ,OAAO,SAASA,CAAI,CAAC,EAFpF,CAAC,CAGZ,CACA,SAASC,EAAqBC,EAAQ,CACpC,OAAOA,EAAO,KAAK,GAAG,CACxB,CACO,IAAMC,EAAuB,CAClC,cAAeJ,GAASD,EAAiBC,CAAK,EAC9C,YAAaG,GAAUA,EAAO,OAAS,EAAID,EAAqBC,CAAM,EAAI,KAC1E,aAAcH,GACR,MAAM,QAAQA,CAAK,EACdA,EAAM,IAAI,MAAM,EAAE,OAAOC,GAAQ,OAAO,SAASA,CAAI,CAAC,EAE3D,OAAOD,GAAU,UAAY,OAAO,SAASA,CAAK,EAC7C,CAACA,CAAK,EAEX,OAAOA,GAAU,SACZD,EAAiBC,CAAK,EAExB,CAAC,CAEZ,EACA,SAASK,EAAcF,EAAQ,CAC7B,MAAO,CAAC,GAAG,IAAI,IAAIA,EAAO,IAAIF,GAAQA,EAAK,KAAK,CAAC,EAAE,OAAO,OAAO,CAAC,CAAC,CACrE,CCtDO,IAAMK,EAAuB,uBAuCpC,IAAMC,EAAqB,CACzB,KAAMC,GAAQ,CACZ,IAAMC,EAAQ,QAAQ,IAAID,EAAM,OAAO,EACvC,OAAO,OAAOC,GAAU,SAAWA,EAAQD,EAAK,aAAa,OAAO,GAAK,EAC3E,EACA,MAAO,CAACA,EAAMC,IAAU,CACtB,IAAMC,EAAOD,GAAS,KAAO,GAAK,OAAOA,CAAK,EAC9CD,EAAK,aAAa,QAASE,CAAI,EAC3B,UAAWF,GACb,QAAQ,IAAIA,EAAM,QAASE,CAAI,CAEnC,CACF,EACMC,EAAqB,CACzB,KAAMH,GAAQ,CACZ,IAAMC,EAAQ,QAAQ,IAAID,EAAM,OAAO,EACvC,GAAI,OAAOC,GAAU,SACnB,OAAOA,EAET,IAAMG,EAAMJ,EAAK,aAAa,OAAO,EACrC,OAAOI,GAAO,MAAQA,IAAQ,GAAK,GAAK,OAAOA,CAAG,CACpD,EACA,MAAO,CAACJ,EAAMC,IAAU,CACtB,IAAMC,EAAOD,GAAS,KAAO,GAAK,OAAOA,CAAK,EAC9CD,EAAK,aAAa,QAASE,CAAI,EAC3B,UAAWF,GACb,QAAQ,IAAIA,EAAM,QAASC,CAAK,CAEpC,CACF,EACMI,EAAsB,CAC1B,KAAML,GACUA,EAAK,cAAc,wBAAwB,GAC3C,SAAWA,EAAK,aAAa,SAAS,EAEtD,MAAO,CAACA,EAAMC,IAAU,CAClBA,EACFD,EAAK,aAAa,UAAW,EAAE,EAE/BA,EAAK,gBAAgB,SAAS,CAElC,CACF,EACA,SAASM,EAAcN,EAAMO,EAAW,CACtC,IAAMN,EAAQ,QAAQ,IAAID,EAAM,OAAO,EACvC,OAAIC,IAAU,QAAUM,EAAU,aACzBA,EAAU,aAAaN,CAAK,EAEjCM,EAAU,cACLA,EAAU,cAAcP,EAAK,aAAa,OAAO,CAAC,EAEpDC,CACT,CACA,SAASO,EAAeR,EAAMC,EAAO,CACnC,QAAQ,IAAID,EAAM,QAASC,CAAK,CAClC,CACA,IAAMQ,EAA0B,CAC9B,KAAMT,GAAQM,EAAcN,EAAMU,CAAmB,EACrD,MAAOF,CACT,EACMG,EAAqB,CACzB,KAAMX,GAAQM,EAAcN,EAAMY,CAAoB,EACtD,MAAOJ,CACT,EACMK,EAAwC,IAAI,IAAI,CAAC,CAAC,eAAgBR,CAAmB,EAAG,CAAC,aAAcA,CAAmB,EAAG,CAAC,eAAgB,CAClJ,GAAGI,EACH,WAAY,MACd,CAAC,EAAG,CAAC,iBAAkBV,CAAkB,EAAG,CAAC,iBAAkB,CAC7D,GAAGA,EACH,WAAY,MACd,CAAC,EAAG,CAAC,wBAAyBA,CAAkB,EAAG,CAAC,aAAc,CAChE,GAAGU,EACH,WAAY,MACd,CAAC,EAAG,CAAC,kBAAmBV,CAAkB,EAAG,CAAC,qBAAsBU,CAAuB,EAAG,CAAC,cAAeA,CAAuB,EAAG,CAAC,gBAAiBA,CAAuB,EAAG,CAAC,aAAc,CACjM,GAAGE,EACH,WAAY,MACd,CAAC,EAAG,CAAC,WAAY,CACf,GAAGR,EACH,WAAY,MACd,CAAC,EAAG,CAAC,mBAAoB,CACvB,GAAGA,EACH,WAAY,MACd,CAAC,CAAC,CAAC,EHzHI,SAASW,EAAS,CACvB,SAAAC,EACA,QAAAC,EACA,MAAOC,EACP,GAAGC,CACL,EAAG,CACD,OAAsBC,EAAI,QAAS,CACjC,GAAGD,EAED,CAACE,CAAoB,EAAG,GAE1B,MAAOC,EAAG,YAAaJ,CAAS,EAChC,QAAAD,EACA,SAAAD,CACF,CAAC,CACH",
4
+ "sourcesContent": ["import { jsx } from \"@ecopages/jsx/jsx-runtime\";\nimport { cx } from \"@/lib/cx\";\nimport { RUI_FIELD_LABEL_ATTR } from \"../form/control-protocol\";\nexport function RuiLabel({\n children,\n htmlFor,\n class: className,\n ...props\n}) {\n return /* @__PURE__ */jsx(\"label\", {\n ...props,\n ...{\n [RUI_FIELD_LABEL_ATTR]: \"\"\n },\n class: cx(\"rui-label\", className),\n for: htmlFor,\n children\n });\n}", "export function cx(...parts) {\n return parts.filter(Boolean).join(\" \");\n}", "export function parseMultiValue(value) {\n if (!value) {\n return [];\n }\n return uniqueTrimmed(value.split(\",\"));\n}\nexport function serializeMultiValue(values) {\n return values.join(\",\");\n}\nexport const multiValueTransform = {\n fromAttribute: value => parseMultiValue(value),\n toAttribute: values => values.length > 0 ? serializeMultiValue(values) : null,\n fromProperty: value => {\n if (Array.isArray(value)) {\n return uniqueTrimmed(value.map(String));\n }\n if (typeof value === \"string\") {\n return parseMultiValue(value);\n }\n return [];\n }\n};\nexport const multiValuePropOptions = {\n type: Array,\n reflect: true,\n transform: multiValueTransform\n};\nexport function parseViewValue(value) {\n return multiValueTransform.fromProperty?.(value) ?? [];\n}\nfunction parseNumberArray(value) {\n if (!value) {\n return [];\n }\n return value.split(\",\").map(item => Number(item.trim())).filter(item => Number.isFinite(item));\n}\nfunction serializeNumberArray(values) {\n return values.join(\",\");\n}\nexport const numberArrayTransform = {\n fromAttribute: value => parseNumberArray(value),\n toAttribute: values => values.length > 0 ? serializeNumberArray(values) : null,\n fromProperty: value => {\n if (Array.isArray(value)) {\n return value.map(Number).filter(item => Number.isFinite(item));\n }\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return [value];\n }\n if (typeof value === \"string\") {\n return parseNumberArray(value);\n }\n return [];\n }\n};\nfunction uniqueTrimmed(values) {\n return [...new Set(values.map(item => item.trim()).filter(Boolean))];\n}", "import { multiValueTransform, numberArrayTransform } from \"../shared/multi-value\";\nexport const RUI_CONTROL_ATTR = \"data-rui-control\";\nexport const RUI_FIELD_MANAGED_ATTR = \"data-rui-field-managed\";\nexport const RUI_FIELD_LABEL_ATTR = \"data-rui-field-label\";\nexport const RUI_FIELD_DESCRIPTION_ATTR = \"data-rui-field-description\";\nexport const RUI_FIELD_ERROR_ATTR = \"data-rui-field-error\";\nexport const RUI_FIELD_DEFAULT_VALUE_ATTR = \"data-default-value\";\nexport const RUI_FORM_DEFAULT_VALUES_ATTR = \"data-default-values\";\nexport const RUI_ARIA_TARGET_ATTR = \"data-rui-aria-target\";\nexport const RUI_ARIA_TARGETS_ATTR = \"data-rui-aria-targets\";\nconst FIELD_COLUMN_SELECTOR = '[data-ref=\"field\"]';\nfunction fieldControlSelector() {\n return `[${RUI_CONTROL_ATTR}], ${hostControlSelector()}`;\n}\nfunction hostControlSelector() {\n return Array.from(CONTROL_VALUE_ADAPTERS.keys()).join(\", \");\n}\nfunction isEmbeddedListbox(node) {\n return node.localName === \"rui-listbox\" && (node.hasAttribute(\"embedded\") || Reflect.get(node, \"embedded\") === true);\n}\nconst ARIA_TARGET_SELECTORS = {\n \"rui-combobox\": \"[data-combobox-input]\",\n \"rui-select\": \"[data-select-trigger]\",\n \"rui-tag-group\": \"[data-tag-list]\",\n \"rui-number-field\": \"[data-number-field-input], input\",\n \"rui-knob\": \"[data-knob-control]\",\n \"rui-checkbox\": \"input\",\n \"rui-checkbox-group\": \"[data-checkbox-group-root]\",\n \"rui-switch\": \"input\"\n};\nexport function isNativeTextControl(node) {\n return node.localName === \"input\" || node.localName === \"textarea\";\n}\nfunction isNativeInput(node) {\n return node.localName === \"input\";\n}\nfunction isNativeTextarea(node) {\n return node.localName === \"textarea\";\n}\nexport function isFormAssociatedHost(host) {\n return Reflect.get(host.constructor, \"formAssociated\") === true;\n}\nconst stringValueAdapter = {\n read: host => {\n const value = Reflect.get(host, \"value\");\n return typeof value === \"string\" ? value : host.getAttribute(\"value\") ?? \"\";\n },\n write: (host, value) => {\n const next = value == null ? \"\" : String(value);\n host.setAttribute(\"value\", next);\n if (\"value\" in host) {\n Reflect.set(host, \"value\", next);\n }\n }\n};\nconst numberValueAdapter = {\n read: host => {\n const value = Reflect.get(host, \"value\");\n if (typeof value === \"number\") {\n return value;\n }\n const raw = host.getAttribute(\"value\");\n return raw == null || raw === \"\" ? \"\" : Number(raw);\n },\n write: (host, value) => {\n const next = value == null ? \"\" : String(value);\n host.setAttribute(\"value\", next);\n if (\"value\" in host) {\n Reflect.set(host, \"value\", value);\n }\n }\n};\nconst booleanValueAdapter = {\n read: host => {\n const input = host.querySelector('input[type=\"checkbox\"]');\n return input?.checked ?? host.hasAttribute(\"checked\");\n },\n write: (host, value) => {\n if (value) {\n host.setAttribute(\"checked\", \"\");\n } else {\n host.removeAttribute(\"checked\");\n }\n }\n};\nfunction readHostValue(host, transform) {\n const value = Reflect.get(host, \"value\");\n if (value !== void 0 && transform.fromProperty) {\n return transform.fromProperty(value);\n }\n if (transform.fromAttribute) {\n return transform.fromAttribute(host.getAttribute(\"value\"));\n }\n return value;\n}\nfunction writeHostValue(host, value) {\n Reflect.set(host, \"value\", value);\n}\nconst stringArrayValueAdapter = {\n read: host => readHostValue(host, multiValueTransform),\n write: writeHostValue\n};\nconst sliderValueAdapter = {\n read: host => readHostValue(host, numberArrayTransform),\n write: writeHostValue\n};\nconst CONTROL_VALUE_ADAPTERS = /* @__PURE__ */new Map([[\"rui-checkbox\", booleanValueAdapter], [\"rui-switch\", booleanValueAdapter], [\"rui-combobox\", {\n ...stringArrayValueAdapter,\n submission: \"none\"\n}], [\"rui-date-field\", stringValueAdapter], [\"rui-date-input\", {\n ...stringValueAdapter,\n submission: \"host\"\n}], [\"rui-date-range-picker\", stringValueAdapter], [\"rui-select\", {\n ...stringArrayValueAdapter,\n submission: \"none\"\n}], [\"rui-radio-group\", stringValueAdapter], [\"rui-checkbox-group\", stringArrayValueAdapter], [\"rui-listbox\", stringArrayValueAdapter], [\"rui-tag-group\", stringArrayValueAdapter], [\"rui-slider\", {\n ...sliderValueAdapter,\n submission: \"host\"\n}], [\"rui-knob\", {\n ...numberValueAdapter,\n submission: \"host\"\n}], [\"rui-number-field\", {\n ...numberValueAdapter,\n submission: \"host\"\n}]]);\nfunction forEachFieldContentNode(root, visit) {\n const slotHost = root;\n const visited = /* @__PURE__ */new Set();\n const safeVisit = node => {\n if (visited.has(node)) {\n return;\n }\n visited.add(node);\n visit(node);\n };\n if (typeof slotHost.getSlotElements === \"function\") {\n for (const node of slotHost.getSlotElements()) {\n safeVisit(node);\n }\n }\n const renderRoot = root.querySelector(FIELD_COLUMN_SELECTOR) ?? root;\n for (const child of Array.from(renderRoot.children)) {\n safeVisit(child);\n }\n for (const node of renderRoot.querySelectorAll(\"*\")) {\n safeVisit(node);\n }\n for (const child of Array.from(root.children)) {\n safeVisit(child);\n }\n const shadow = root.shadowRoot;\n if (shadow) {\n for (const child of Array.from(shadow.children)) {\n safeVisit(child);\n }\n }\n}\nfunction queryFieldContent(root, selector) {\n let found = null;\n forEachFieldContentNode(root, node => {\n if (found || !(node instanceof HTMLElement)) {\n return;\n }\n if (node.matches(selector)) {\n found = node;\n return;\n }\n found = node.querySelector(selector);\n });\n return found;\n}\nfunction pickPrimaryFieldControl(candidates) {\n const eligibleCandidates = candidates.filter(candidate => !isEmbeddedListbox(candidate));\n if (eligibleCandidates.length === 0) {\n return null;\n }\n return eligibleCandidates.find(candidate => !eligibleCandidates.some(ancestor => ancestor !== candidate && ancestor.contains(candidate))) ?? null;\n}\nfunction collectFieldControls(root) {\n const candidates = [];\n forEachFieldContentNode(root, node => {\n if (node instanceof HTMLElement && node.matches(fieldControlSelector())) {\n candidates.push(node);\n }\n });\n return candidates;\n}\nfunction listFieldControlsInRenderTree(root) {\n const renderRoot = root.querySelector(FIELD_COLUMN_SELECTOR);\n if (!(renderRoot instanceof HTMLElement)) {\n return [];\n }\n return Array.from(renderRoot.querySelectorAll(fieldControlSelector())).filter(el => root.contains(el));\n}\nexport function findFieldControl(root) {\n const fromRenderTree = pickPrimaryFieldControl(listFieldControlsInRenderTree(root));\n if (fromRenderTree) {\n return fromRenderTree;\n }\n return pickPrimaryFieldControl(collectFieldControls(root));\n}\nexport function registerFieldControl(tagName, adapter) {\n const tag = tagName.toLowerCase();\n CONTROL_VALUE_ADAPTERS.set(tag, adapter);\n}\nexport function isPrimaryFieldControlEvent(root, event) {\n const control = findFieldControl(root);\n if (!control || !(event.target instanceof Element)) {\n return false;\n }\n if (event.target !== control && !control.contains(event.target)) {\n return false;\n }\n const nestedHost = event.target.closest(hostControlSelector());\n return nestedHost === control || nestedHost == null;\n}\nexport function readControlValue(control) {\n if (isNativeInput(control)) {\n const host2 = resolveControlHost(control);\n const adapter = host2 === control ? void 0 : CONTROL_VALUE_ADAPTERS.get(host2.localName);\n if (adapter) {\n return adapter.read(host2);\n }\n if (control.type === \"checkbox\") {\n return control.checked;\n }\n if (control.type === \"number\" || control.type === \"range\") {\n return control.value === \"\" ? \"\" : Number(control.value);\n }\n return control.value;\n }\n if (isNativeTextarea(control)) {\n return control.value;\n }\n const host = resolveControlHost(control);\n return CONTROL_VALUE_ADAPTERS.get(host.localName)?.read(host) ?? host.getAttribute(\"value\") ?? \"\";\n}\nexport function writeControlValue(control, value) {\n if (isNativeInput(control)) {\n const host2 = resolveControlHost(control);\n const adapter = host2 === control ? void 0 : CONTROL_VALUE_ADAPTERS.get(host2.localName);\n if (adapter) {\n adapter.write(host2, value);\n return;\n }\n if (control.type === \"checkbox\") {\n control.checked = Boolean(value);\n const ce = control.closest(\"rui-checkbox, rui-switch\");\n if (ce) {\n if (value) {\n ce.setAttribute(\"checked\", \"\");\n } else {\n ce.removeAttribute(\"checked\");\n }\n }\n return;\n }\n control.value = value == null ? \"\" : String(value);\n return;\n }\n if (isNativeTextarea(control)) {\n control.value = value == null ? \"\" : String(value);\n return;\n }\n const host = resolveControlHost(control);\n CONTROL_VALUE_ADAPTERS.get(host.localName)?.write(host, value);\n}\nfunction resolveControlHost(control) {\n if (control.hasAttribute(RUI_CONTROL_ATTR)) {\n const host = control.closest(hostControlSelector());\n return host ?? control;\n }\n return control;\n}\nexport function findFieldLabel(root) {\n return queryFieldContent(root, `[${RUI_FIELD_LABEL_ATTR}]`);\n}\nexport function findFieldDescription(root) {\n return queryFieldContent(root, `[${RUI_FIELD_DESCRIPTION_ATTR}]`);\n}\nexport function findFieldError(root) {\n const all = findFieldErrorElements(root);\n return all[0] ?? null;\n}\nexport function findFieldErrorElements(root) {\n const renderRoot = root.querySelector(FIELD_COLUMN_SELECTOR);\n if (renderRoot instanceof HTMLElement) {\n const inRender = Array.from(renderRoot.querySelectorAll(`[${RUI_FIELD_ERROR_ATTR}]`));\n if (inRender.length > 0) {\n return inRender;\n }\n }\n const fromDom = Array.from(root.querySelectorAll(`[${RUI_FIELD_ERROR_ATTR}]`));\n if (fromDom.length > 0) {\n return fromDom;\n }\n const single = queryFieldContent(root, `[${RUI_FIELD_ERROR_ATTR}]`);\n return single ? [single] : [];\n}\nexport function wireFieldControlName(controlHost, ariaTarget, name) {\n if (ariaTarget && isNativeTextControl(ariaTarget)) {\n const submission = controlHost && CONTROL_VALUE_ADAPTERS.get(controlHost.localName)?.submission;\n const namesInner = controlHost == null || controlHost === ariaTarget || !isFormAssociatedHost(controlHost) && submission !== \"host\" && submission !== \"none\";\n if (namesInner && name) {\n ariaTarget.name = name;\n } else {\n ariaTarget.removeAttribute(\"name\");\n }\n }\n if (controlHost && CONTROL_VALUE_ADAPTERS.has(controlHost.localName)) {\n Reflect.set(controlHost, \"name\", name);\n if (name) controlHost.setAttribute(\"name\", name);else controlHost.removeAttribute(\"name\");\n }\n}\nfunction isChecked(input) {\n const checked = Reflect.get(input, \"checked\");\n return typeof checked === \"boolean\" ? checked : input.hasAttribute(\"checked\");\n}\nfunction resolveDeclaredAriaTarget(control) {\n const multi = control.getAttribute(RUI_ARIA_TARGETS_ATTR);\n if (multi) {\n const firstSelector = multi.split(\",\")[0]?.trim();\n if (firstSelector) {\n return control.querySelector(firstSelector);\n }\n }\n const single = control.getAttribute(RUI_ARIA_TARGET_ATTR);\n if (single) {\n return control.querySelector(single);\n }\n return null;\n}\nfunction resolveDeclaredAriaTargets(control) {\n const multi = control.getAttribute(RUI_ARIA_TARGETS_ATTR);\n if (multi) {\n return multi.split(\",\").map(selector => selector.trim()).filter(selector => selector !== \"\").map(selector => control.querySelector(selector)).filter(node => node != null);\n }\n const single = control.getAttribute(RUI_ARIA_TARGET_ATTR);\n if (single) {\n const target = control.querySelector(single);\n return target ? [target] : [];\n }\n return [];\n}\nexport function getAriaControlTarget(control) {\n if (isNativeTextControl(control)) {\n return control;\n }\n const declared = resolveDeclaredAriaTarget(control);\n if (declared) {\n return declared;\n }\n if (control.hasAttribute(RUI_CONTROL_ATTR)) {\n return control;\n }\n if (control.localName === \"rui-slider\") {\n const thumb = Array.from(control.querySelectorAll(\"[data-thumb]\")).find(node => !node.hasAttribute(\"hidden\"));\n return thumb ?? control;\n }\n const marked = control.querySelector(`[${RUI_CONTROL_ATTR}]`);\n if (marked) {\n return marked;\n }\n if (control.localName === \"rui-radio-group\") {\n return getSelectedRadio(control) ?? control;\n }\n const selector = ARIA_TARGET_SELECTORS[control.localName];\n return selector ? control.querySelector(selector) ?? control : control;\n}\nfunction getSelectedRadio(control) {\n const radios = control.querySelectorAll('input[type=\"radio\"]');\n return Array.from(radios).find(isChecked) ?? radios[0];\n}\nexport function getAriaControlTargets(control) {\n const declared = resolveDeclaredAriaTargets(control);\n if (declared.length > 0) {\n return declared;\n }\n if (control.localName === \"rui-slider\") {\n const thumbs = Array.from(control.querySelectorAll(\"[data-thumb]\")).filter(node => !node.hasAttribute(\"hidden\"));\n return thumbs.length > 0 ? thumbs : [control];\n }\n return [getAriaControlTarget(control)];\n}"],
5
+ "mappings": "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",
6
6
  "names": ["jsx", "cx", "parts", "parseMultiValue", "value", "uniqueTrimmed", "serializeMultiValue", "values", "multiValueTransform", "parseNumberArray", "value", "item", "serializeNumberArray", "values", "numberArrayTransform", "uniqueTrimmed", "RUI_FIELD_LABEL_ATTR", "stringValueAdapter", "host", "value", "next", "numberValueAdapter", "raw", "booleanValueAdapter", "readHostValue", "transform", "writeHostValue", "stringArrayValueAdapter", "multiValueTransform", "sliderValueAdapter", "numberArrayTransform", "CONTROL_VALUE_ADAPTERS", "RuiLabel", "children", "htmlFor", "className", "props", "jsx", "RUI_FIELD_LABEL_ATTR", "cx"]
7
7
  }
@@ -1,5 +1,9 @@
1
1
  import type { JsxElementProps } from '@ecopages/jsx';
2
2
  export type RuiLabelProps = JsxElementProps<HTMLLabelElement> & {
3
+ /**
4
+ * Control id. Rendered as the HTML `for` attribute; this JSX runtime does not
5
+ * alias `htmlFor`.
6
+ */
3
7
  htmlFor?: string;
4
8
  };
5
9
  /**
@@ -1,4 +1,5 @@
1
1
  import type { JsxCustomElementAttributes, JsxElementProps, JsxRenderable } from '@ecopages/jsx';
2
+ import type { NativeButtonProps } from '@/lib/native-element-props';
2
3
  import { type RuiButtonControlProps } from '../button';
3
4
  import { type RuiMenuEntry } from '../shared/menu-entry';
4
5
  import type { RuiMenuButton as RuiMenuButtonElement, RuiMenuButtonProps } from './menu-button.script';
@@ -18,7 +19,7 @@ export type RuiMenuButtonSubmenuContentProps = JsxElementProps<HTMLDivElement>;
18
19
  * @cssclass rui-menu-button__submenu - Nested popup menu surface.
19
20
  */
20
21
  export declare function RuiMenuButtonSubmenuContent({ children, class: className, ...props }: RuiMenuButtonSubmenuContentProps): JsxRenderable;
21
- export type RuiMenuButtonItemProps = JsxElementProps<HTMLButtonElement> & {
22
+ export type RuiMenuButtonItemProps = NativeButtonProps & {
22
23
  value: string;
23
24
  disabled?: boolean;
24
25
  hasSubmenu?: boolean;
@@ -1,4 +1,5 @@
1
1
  import type { JsxCustomElementAttributes, JsxElementProps, JsxRenderable } from '@ecopages/jsx';
2
+ import type { NativeButtonProps } from '@/lib/native-element-props';
2
3
  import { type RuiMenuEntry } from '../shared/menu-entry';
3
4
  import type { RuiMenubar as RuiMenubarElement, RuiMenubarProps } from './menubar.script';
4
5
  import './menubar.script';
@@ -17,7 +18,7 @@ export type RuiMenubarMenuProps = {
17
18
  };
18
19
  /** Top-level menubar menu containing a trigger and its popup content. */
19
20
  export declare function RuiMenubarMenu({ label, children, disabled }: RuiMenubarMenuProps): JsxRenderable;
20
- export type RuiMenubarMenuItemProps = Omit<JsxElementProps<HTMLButtonElement>, 'value'> & {
21
+ export type RuiMenubarMenuItemProps = NativeButtonProps & {
21
22
  value: string;
22
23
  disabled?: boolean;
23
24
  hasSubmenu?: boolean;
@@ -1,4 +1,5 @@
1
1
  import type { JsxCustomElementAttributes, JsxElementProps } from '@ecopages/jsx';
2
+ import type { NativeButtonProps, NativeInputProps } from '@/lib/native-element-props';
2
3
  import type { RuiNumberField as RuiNumberFieldElement, RuiNumberFieldProps } from './number-field.script';
3
4
  import './number-field.script';
4
5
  export type RuiNumberFieldGroupProps = JsxElementProps<HTMLDivElement>;
@@ -8,7 +9,7 @@ export type RuiNumberFieldGroupProps = JsxElementProps<HTMLDivElement>;
8
9
  * @cssclass rui-number-field__group - Control-height bordered row wrapping input and steppers.
9
10
  */
10
11
  export declare function RuiNumberFieldGroup({ children, class: className, ...props }: RuiNumberFieldGroupProps): import("@ecopages/jsx").JsxRenderable;
11
- export type RuiNumberFieldInputProps = JsxElementProps<HTMLInputElement> & {
12
+ export type RuiNumberFieldInputProps = NativeInputProps & {
12
13
  placeholder?: string;
13
14
  disabled?: boolean;
14
15
  readOnly?: boolean;
@@ -27,7 +28,7 @@ export type RuiNumberFieldSteppersProps = JsxElementProps<HTMLDivElement>;
27
28
  * @cssclass rui-number-field__steppers - Trailing stepper column with a border divider.
28
29
  */
29
30
  export declare function RuiNumberFieldSteppers({ children, class: className, ...props }: RuiNumberFieldSteppersProps): import("@ecopages/jsx").JsxRenderable;
30
- export type RuiNumberFieldStepperButtonProps = JsxElementProps<HTMLButtonElement> & {
31
+ export type RuiNumberFieldStepperButtonProps = NativeButtonProps & {
31
32
  disabled?: boolean;
32
33
  };
33
34
  /**
@@ -1,4 +1,5 @@
1
1
  import type { JsxCustomElementAttributes, JsxElementProps, JsxRenderable } from '@ecopages/jsx';
2
+ import type { NativeButtonProps, NativeInputProps } from '@/lib/native-element-props';
2
3
  import { type RuiListboxOptionData } from '../listbox';
3
4
  import type { RuiSelect as RuiSelectElement, RuiSelectProps } from './select.script';
4
5
  import './select.script';
@@ -21,12 +22,12 @@ export type RuiSelectTriggerProps = JsxElementProps<HTMLDivElement> & {
21
22
  * @cssclass rui-select__trigger - Combobox surface; `role="combobox"` set by the controller.
22
23
  */
23
24
  export declare function RuiSelectTrigger({ children, class: className, disabled, ...props }: RuiSelectTriggerProps): JsxRenderable;
24
- export type RuiSelectToggleProps = JsxElementProps<HTMLButtonElement> & {
25
+ export type RuiSelectToggleProps = NativeButtonProps & {
25
26
  disabled?: boolean;
26
27
  };
27
28
  /** Toggle button for opening the listbox popup. Stamps `[data-select-toggle]`. Children replace the default chevron icon. */
28
29
  export declare function RuiSelectToggle({ children, class: className, aria, disabled, ...props }: RuiSelectToggleProps): JsxRenderable;
29
- export type RuiSelectClearProps = JsxElementProps<HTMLButtonElement> & {
30
+ export type RuiSelectClearProps = NativeButtonProps & {
30
31
  disabled?: boolean;
31
32
  };
32
33
  /** Clears the current selection. Stamps `[data-select-clear]`. Place next to `RuiSelectToggle`. Children replace the default close icon. */
@@ -50,7 +51,7 @@ export type RuiSelectListboxProps = JsxElementProps<HTMLDivElement>;
50
51
  * @cssclass rui-select__listbox - Popup shell; composes `rui-popover` surface roles.
51
52
  */
52
53
  export declare function RuiSelectListbox({ children, class: className, ...props }: RuiSelectListboxProps): JsxRenderable;
53
- export type RuiSelectSearchProps = JsxElementProps<HTMLInputElement> & {
54
+ export type RuiSelectSearchProps = NativeInputProps & {
54
55
  placeholder?: string;
55
56
  disabled?: boolean;
56
57
  };
@@ -1,4 +1,5 @@
1
1
  import { type JsxCustomElementAttributes, type JsxElementProps, type JsxRenderable } from '@ecopages/jsx';
2
+ import type { NativeButtonProps } from '@/lib/native-element-props';
2
3
  import type { RuiSidebar as RuiSidebarElement, RuiSidebarProps } from './sidebar.script';
3
4
  import './sidebar.script';
4
5
  import './sidebar-trigger.script';
@@ -70,7 +71,7 @@ export type RuiSidebarGroupLabelProps = JsxElementProps<HTMLHeadingElement>;
70
71
  * @cssclass rui-sidebar__group-label - Group heading (`<h2>`).
71
72
  */
72
73
  export declare function RuiSidebarGroupLabel({ children, class: className, ...props }: RuiSidebarGroupLabelProps): JsxRenderable;
73
- export type RuiSidebarGroupActionProps = JsxElementProps<HTMLButtonElement>;
74
+ export type RuiSidebarGroupActionProps = NativeButtonProps;
74
75
  /**
75
76
  * Top-right action button inside a group header.
76
77
  *
@@ -107,7 +108,7 @@ type RuiSidebarMenuButtonChrome = {
107
108
  /** Optional tooltip label for collapsed-icon mode. */
108
109
  tooltip?: string;
109
110
  };
110
- export type RuiSidebarMenuButtonControlProps = JsxElementProps<HTMLButtonElement> & RuiSidebarMenuButtonChrome & {
111
+ export type RuiSidebarMenuButtonControlProps = NativeButtonProps & RuiSidebarMenuButtonChrome & {
111
112
  as?: 'button';
112
113
  href?: never;
113
114
  type?: 'button' | 'submit' | 'reset';
@@ -1,8 +1,9 @@
1
1
  import type { JsxCustomElementAttributes, JsxElementProps } from '@ecopages/jsx';
2
+ import type { NativeButtonProps } from '@/lib/native-element-props';
2
3
  import type { RuiTabs as RuiTabsElement, RuiTabsProps } from './tabs.script';
3
4
  import './tabs.script';
4
5
  export type RuiTabListProps = JsxElementProps<HTMLDivElement>;
5
- export type RuiTabProps = Omit<JsxElementProps<HTMLButtonElement>, 'id'> & {
6
+ export type RuiTabProps = NativeButtonProps & {
6
7
  id: string;
7
8
  disabled?: boolean;
8
9
  /** Whether this tab is selected in the initial document. */
@@ -1,4 +1,5 @@
1
1
  import { type JsxCustomElementAttributes, type JsxElementProps, type JsxRenderable } from '@ecopages/jsx';
2
+ import type { NativeButtonProps } from '@/lib/native-element-props';
2
3
  import type { RuiTagGroup as RuiTagGroupElement, RuiTagGroupProps } from './tag-group.script';
3
4
  import './tag-group.script';
4
5
  export type RuiTagListProps = JsxElementProps<HTMLDivElement>;
@@ -26,7 +27,7 @@ export type RuiTagProps = JsxElementProps<HTMLSpanElement> & {
26
27
  * `createManagedTag` always include a remove control — edit both together.
27
28
  */
28
29
  export declare function RuiTag({ value, label, children, class: className, disabled, aria, ...props }: RuiTagProps): JsxRenderable;
29
- export type RuiTagRemoveProps = JsxElementProps<HTMLButtonElement>;
30
+ export type RuiTagRemoveProps = NativeButtonProps;
30
31
  /**
31
32
  * Remove control inside a tag. Stamps `[data-tag-remove]`.
32
33
  *
@@ -1,5 +1,5 @@
1
- import type { JsxElementProps } from '@ecopages/jsx';
2
- export type RuiTextareaProps = JsxElementProps<HTMLTextAreaElement> & {
1
+ import type { NativeTextareaProps } from '@/lib/native-element-props';
2
+ export type RuiTextareaProps = NativeTextareaProps & {
3
3
  value?: string;
4
4
  placeholder?: string;
5
5
  disabled?: boolean;
@@ -11,6 +11,7 @@ export type RuiTextareaProps = JsxElementProps<HTMLTextAreaElement> & {
11
11
  *
12
12
  * No custom element — Field owns labeling, `aria-*`, and validation wiring.
13
13
  * Marked with `data-rui-control` so `<rui-field>` can discover it.
14
+ * Native `<textarea>` attributes (`required`, `maxlength`, `autocomplete`, …) are part of the props type.
14
15
  *
15
16
  * @remarks
16
17
  * Padding and type use the same `--space-control-*` / `--text-control` tokens as