@pearpages/pulp-react 0.2.2 → 0.3.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.
Files changed (156) hide show
  1. package/README.md +14 -0
  2. package/dist/accordion.js +1 -1
  3. package/dist/alert.css +18 -0
  4. package/dist/alert.css.map +1 -1
  5. package/dist/alert.js +4 -4
  6. package/dist/avatar.css +46 -0
  7. package/dist/avatar.css.map +1 -0
  8. package/dist/avatar.d.ts +41 -0
  9. package/dist/avatar.js +5 -0
  10. package/dist/avatar.js.map +1 -0
  11. package/dist/badge.css +37 -0
  12. package/dist/badge.css.map +1 -1
  13. package/dist/badge.d.ts +22 -5
  14. package/dist/badge.js +2 -1
  15. package/dist/button.css +18 -0
  16. package/dist/button.css.map +1 -1
  17. package/dist/button.d.ts +11 -2
  18. package/dist/button.js +2 -2
  19. package/dist/calendar.js +1 -1
  20. package/dist/card.js +2 -2
  21. package/dist/checkbox.js +4 -4
  22. package/dist/chip.css +95 -0
  23. package/dist/chip.css.map +1 -0
  24. package/dist/chip.d.ts +43 -0
  25. package/dist/chip.js +4 -0
  26. package/dist/chip.js.map +1 -0
  27. package/dist/{chunk-N6E2E2OY.js → chunk-2NVC3C7K.js} +3 -3
  28. package/dist/{chunk-N6E2E2OY.js.map → chunk-2NVC3C7K.js.map} +1 -1
  29. package/dist/{chunk-MF66ICX6.js → chunk-56RSH7GQ.js} +3 -3
  30. package/dist/{chunk-MF66ICX6.js.map → chunk-56RSH7GQ.js.map} +1 -1
  31. package/dist/chunk-5TYCIBLW.js +27 -0
  32. package/dist/chunk-5TYCIBLW.js.map +1 -0
  33. package/dist/chunk-7O6FTCZL.js +101 -0
  34. package/dist/chunk-7O6FTCZL.js.map +1 -0
  35. package/dist/{chunk-N4C3NQIN.js → chunk-A7TMFEQ2.js} +3 -3
  36. package/dist/{chunk-N4C3NQIN.js.map → chunk-A7TMFEQ2.js.map} +1 -1
  37. package/dist/{chunk-2NSQPN7S.js → chunk-AZAI4OVR.js} +3 -3
  38. package/dist/{chunk-2NSQPN7S.js.map → chunk-AZAI4OVR.js.map} +1 -1
  39. package/dist/{chunk-DVZ46GQN.js → chunk-CLE2QGCU.js} +3 -3
  40. package/dist/{chunk-DVZ46GQN.js.map → chunk-CLE2QGCU.js.map} +1 -1
  41. package/dist/{chunk-5TTYVQ6Q.js → chunk-DE67ECD7.js} +5 -3
  42. package/dist/chunk-DE67ECD7.js.map +1 -0
  43. package/dist/{chunk-BAPNIZDV.js → chunk-F2YI5N4L.js} +3 -3
  44. package/dist/chunk-F2YI5N4L.js.map +1 -0
  45. package/dist/{chunk-U3N3G2UA.js → chunk-FFCEY76B.js} +10 -5
  46. package/dist/chunk-FFCEY76B.js.map +1 -0
  47. package/dist/{chunk-XWPXW46D.js → chunk-GWTHITZO.js} +3 -3
  48. package/dist/{chunk-XWPXW46D.js.map → chunk-GWTHITZO.js.map} +1 -1
  49. package/dist/chunk-HDC2IQV2.js +34 -0
  50. package/dist/chunk-HDC2IQV2.js.map +1 -0
  51. package/dist/{chunk-VQN5DQP6.js → chunk-HKNIEQ2V.js} +4 -4
  52. package/dist/{chunk-VQN5DQP6.js.map → chunk-HKNIEQ2V.js.map} +1 -1
  53. package/dist/{chunk-LA3YBXCR.js → chunk-HPQ462R5.js} +3 -3
  54. package/dist/{chunk-LA3YBXCR.js.map → chunk-HPQ462R5.js.map} +1 -1
  55. package/dist/chunk-KSLKNWWM.js +28 -0
  56. package/dist/chunk-KSLKNWWM.js.map +1 -0
  57. package/dist/chunk-OKA2PLDV.js +85 -0
  58. package/dist/chunk-OKA2PLDV.js.map +1 -0
  59. package/dist/{chunk-6BIEW4WJ.js → chunk-Q6SYKNZ5.js} +3 -3
  60. package/dist/{chunk-6BIEW4WJ.js.map → chunk-Q6SYKNZ5.js.map} +1 -1
  61. package/dist/chunk-QID6YYFF.js +33 -0
  62. package/dist/chunk-QID6YYFF.js.map +1 -0
  63. package/dist/{chunk-ZVDN3GRI.js → chunk-QJG5ILK5.js} +3 -3
  64. package/dist/{chunk-ZVDN3GRI.js.map → chunk-QJG5ILK5.js.map} +1 -1
  65. package/dist/chunk-QXHSA4QD.js +43 -0
  66. package/dist/chunk-QXHSA4QD.js.map +1 -0
  67. package/dist/chunk-S632WN4W.js +106 -0
  68. package/dist/chunk-S632WN4W.js.map +1 -0
  69. package/dist/{chunk-OFFFRIJG.js → chunk-SDIK6VSC.js} +3 -3
  70. package/dist/{chunk-OFFFRIJG.js.map → chunk-SDIK6VSC.js.map} +1 -1
  71. package/dist/{chunk-M5VL22MY.js → chunk-SXMORGSG.js} +3 -3
  72. package/dist/{chunk-M5VL22MY.js.map → chunk-SXMORGSG.js.map} +1 -1
  73. package/dist/{chunk-Z6SS4G4V.js → chunk-UMK4D234.js} +3 -3
  74. package/dist/{chunk-Z6SS4G4V.js.map → chunk-UMK4D234.js.map} +1 -1
  75. package/dist/{chunk-5PYLJQJX.js → chunk-VS2HPJIX.js} +3 -3
  76. package/dist/{chunk-5PYLJQJX.js.map → chunk-VS2HPJIX.js.map} +1 -1
  77. package/dist/{chunk-NOUUOH4R.js → chunk-WDIFWMKE.js} +3 -3
  78. package/dist/chunk-WDIFWMKE.js.map +1 -0
  79. package/dist/chunk-Y7KC2FDU.js +88 -0
  80. package/dist/chunk-Y7KC2FDU.js.map +1 -0
  81. package/dist/{chunk-OFKSU77Y.js → chunk-ZEVQQQOA.js} +3 -3
  82. package/dist/{chunk-OFKSU77Y.js.map → chunk-ZEVQQQOA.js.map} +1 -1
  83. package/dist/combobox.css +3 -0
  84. package/dist/combobox.css.map +1 -1
  85. package/dist/combobox.js +2 -2
  86. package/dist/component-manifest.json +679 -8
  87. package/dist/date-picker.js +1 -1
  88. package/dist/dialog.js +1 -1
  89. package/dist/divider.css +37 -0
  90. package/dist/divider.css.map +1 -0
  91. package/dist/divider.d.ts +35 -0
  92. package/dist/divider.js +4 -0
  93. package/dist/divider.js.map +1 -0
  94. package/dist/empty-state.css +175 -0
  95. package/dist/empty-state.css.map +1 -0
  96. package/dist/empty-state.d.ts +40 -0
  97. package/dist/empty-state.js +7 -0
  98. package/dist/empty-state.js.map +1 -0
  99. package/dist/field.js +2 -2
  100. package/dist/icon-button.css +18 -0
  101. package/dist/icon-button.css.map +1 -1
  102. package/dist/icon-button.js +3 -3
  103. package/dist/index.css +489 -0
  104. package/dist/index.css.map +1 -1
  105. package/dist/index.d.ts +8 -2
  106. package/dist/index.js +38 -32
  107. package/dist/link.css +35 -0
  108. package/dist/link.css.map +1 -0
  109. package/dist/link.d.ts +37 -0
  110. package/dist/link.js +5 -0
  111. package/dist/link.js.map +1 -0
  112. package/dist/listbox.js +1 -1
  113. package/dist/menu.js +2 -2
  114. package/dist/pagination.css +18 -0
  115. package/dist/pagination.css.map +1 -1
  116. package/dist/pagination.js +4 -4
  117. package/dist/picker.css +3 -0
  118. package/dist/picker.css.map +1 -1
  119. package/dist/picker.js +2 -2
  120. package/dist/popover.js +2 -2
  121. package/dist/radio.js +3 -3
  122. package/dist/segmented-control.css +111 -0
  123. package/dist/segmented-control.css.map +1 -0
  124. package/dist/segmented-control.d.ts +90 -0
  125. package/dist/segmented-control.js +5 -0
  126. package/dist/segmented-control.js.map +1 -0
  127. package/dist/select.js +3 -3
  128. package/dist/sheet.css +28 -0
  129. package/dist/sheet.css.map +1 -1
  130. package/dist/sheet.d.ts +9 -2
  131. package/dist/sheet.js +1 -1
  132. package/dist/slider.js +1 -1
  133. package/dist/switch.js +4 -4
  134. package/dist/table.js +1 -1
  135. package/dist/tabs.js +1 -1
  136. package/dist/text-field.css +63 -0
  137. package/dist/text-field.css.map +1 -1
  138. package/dist/text-field.d.ts +15 -2
  139. package/dist/text-field.js +3 -3
  140. package/dist/textarea.js +3 -3
  141. package/dist/toast.css +18 -0
  142. package/dist/toast.css.map +1 -1
  143. package/dist/toast.d.ts +21 -3
  144. package/dist/toast.js +5 -5
  145. package/dist/tooltip.js +2 -2
  146. package/package.json +36 -6
  147. package/dist/chunk-5TTYVQ6Q.js.map +0 -1
  148. package/dist/chunk-737GQSOB.js +0 -19
  149. package/dist/chunk-737GQSOB.js.map +0 -1
  150. package/dist/chunk-BAPNIZDV.js.map +0 -1
  151. package/dist/chunk-IFIQLIA3.js +0 -48
  152. package/dist/chunk-IFIQLIA3.js.map +0 -1
  153. package/dist/chunk-NOUUOH4R.js.map +0 -1
  154. package/dist/chunk-TJJBCS3N.js +0 -28
  155. package/dist/chunk-TJJBCS3N.js.map +0 -1
  156. package/dist/chunk-U3N3G2UA.js.map +0 -1
@@ -0,0 +1,33 @@
1
+ import { classes } from './chunk-MI4QUKQS.js';
2
+ import { jsx } from 'react/jsx-runtime';
3
+
4
+ // src/divider/Divider.module.css
5
+ var Divider_default = {
6
+ divider: "Divider_divider"
7
+ };
8
+ function Divider({
9
+ orientation = "horizontal",
10
+ spacing = "none",
11
+ decorative = true,
12
+ className,
13
+ ref,
14
+ ...rest
15
+ }) {
16
+ return /* @__PURE__ */ jsx(
17
+ "div",
18
+ {
19
+ ...rest,
20
+ ref,
21
+ role: decorative ? "none" : "separator",
22
+ "aria-orientation": !decorative && orientation === "vertical" ? "vertical" : void 0,
23
+ className: classes(Divider_default.divider, className),
24
+ "data-orientation": orientation,
25
+ "data-spacing": spacing
26
+ }
27
+ );
28
+ }
29
+ Divider.displayName = "Divider";
30
+
31
+ export { Divider };
32
+ //# sourceMappingURL=chunk-QID6YYFF.js.map
33
+ //# sourceMappingURL=chunk-QID6YYFF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/divider/Divider.module.css","../src/divider/Divider.tsx"],"names":["divider"],"mappings":";;;;AAAA,IAAA,eAAA,GAAA;AAAA,EAKG,OAAA,EAAAA;AAAA,CAAA;AC4BI,SAAS,OAAA,CAAQ;AAAA,EACtB,WAAA,GAAc,YAAA;AAAA,EACd,OAAA,GAAU,MAAA;AAAA,EACV,UAAA,GAAa,IAAA;AAAA,EACb,SAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAG;AACL,CAAA,EAAiB;AACf,EAAA,uBACE,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACE,GAAG,IAAA;AAAA,MACJ,GAAA;AAAA,MACA,IAAA,EAAM,aAAa,MAAA,GAAS,WAAA;AAAA,MAC5B,kBAAA,EAAkB,CAAC,UAAA,IAAc,WAAA,KAAgB,aAAa,UAAA,GAAa,MAAA;AAAA,MAC3E,SAAA,EAAW,OAAA,CAAQ,eAAA,CAAO,OAAA,EAAS,SAAS,CAAA;AAAA,MAC5C,kBAAA,EAAkB,WAAA;AAAA,MAClB,cAAA,EAAc;AAAA;AAAA,GAChB;AAEJ;AAEA,OAAA,CAAQ,WAAA,GAAc,SAAA","file":"chunk-QID6YYFF.js","sourcesContent":["/* Every value is a token: --divider-* in packages/tokens/tokens/component/divider.json */\n\n@layer reset, tokens, vendor, base, components, utilities;\n\n@layer components {\n .divider {\n flex-shrink: 0;\n margin: 0;\n border: 0;\n background-color: var(--divider-color);\n\n &[data-orientation=\"horizontal\"] {\n inline-size: 100%;\n block-size: var(--divider-thickness);\n\n &[data-spacing=\"sm\"] { margin-block: var(--divider-spacing-sm); }\n &[data-spacing=\"md\"] { margin-block: var(--divider-spacing-md); }\n &[data-spacing=\"lg\"] { margin-block: var(--divider-spacing-lg); }\n }\n\n &[data-orientation=\"vertical\"] {\n align-self: stretch;\n inline-size: var(--divider-thickness);\n\n &[data-spacing=\"sm\"] { margin-inline: var(--divider-spacing-sm); }\n &[data-spacing=\"md\"] { margin-inline: var(--divider-spacing-md); }\n &[data-spacing=\"lg\"] { margin-inline: var(--divider-spacing-lg); }\n }\n }\n}\n","import type { HTMLAttributes, Ref } from 'react';\nimport { classes } from '../internal/classes';\nimport styles from './Divider.module.css';\n\nexport type DividerOrientation = 'horizontal' | 'vertical';\nexport type DividerSpacing = 'none' | 'sm' | 'md' | 'lg';\n\nexport interface DividerProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {\n /** @default 'horizontal' */\n orientation?: DividerOrientation;\n /** Space on both sides, along the axis the line separates. @default 'none' */\n spacing?: DividerSpacing;\n /**\n * A decorative line is hidden from assistive technology. Pass `false` when the\n * line is the only thing that says two groups are separate. @default true\n */\n decorative?: boolean;\n\n ref?: Ref<HTMLDivElement>;\n}\n\n/**\n * A hairline between two groups of content, horizontal or vertical. A vertical\n * divider stretches to its flex or grid row, so it needs a parent that lays it out.\n *\n * @status experimental\n * @category Layout\n * @accessibility Decorative by default: `role=\"none\"`, nothing is announced, because headings and landmarks should already carry the structure. With `decorative={false}` it is a `separator`, and a vertical one says so through `aria-orientation`. It is never focusable: a separator that moves is a splitter, which this is not.\n * @do Put it between groups inside a Card, a Menu-like list or a toolbar.\n * @do Let `spacing` set the distance, so it stays on the spacing scale.\n * @dont Use it to draw a border around something; that is the container's border.\n * @dont Rely on it alone to tell a screen reader that a new section starts; use a heading.\n */\nexport function Divider({\n orientation = 'horizontal',\n spacing = 'none',\n decorative = true,\n className,\n ref,\n ...rest\n}: DividerProps) {\n return (\n <div\n {...rest}\n ref={ref}\n role={decorative ? 'none' : 'separator'}\n aria-orientation={!decorative && orientation === 'vertical' ? 'vertical' : undefined}\n className={classes(styles.divider, className)}\n data-orientation={orientation}\n data-spacing={spacing}\n />\n );\n}\n\nDivider.displayName = 'Divider';\n"]}
@@ -44,6 +44,6 @@ function renderAsChild(displayName, children, props, options = {}) {
44
44
  return cloneElement(child, merged);
45
45
  }
46
46
 
47
- export { renderAsChild };
48
- //# sourceMappingURL=chunk-ZVDN3GRI.js.map
49
- //# sourceMappingURL=chunk-ZVDN3GRI.js.map
47
+ export { mergeRefs, renderAsChild };
48
+ //# sourceMappingURL=chunk-QJG5ILK5.js.map
49
+ //# sourceMappingURL=chunk-QJG5ILK5.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/internal/asChild.ts"],"names":[],"mappings":";;;AAQO,SAAS,aAAgB,IAAA,EAAyC;AACvE,EAAA,OAAO,CAAC,KAAA,KAAoB;AAC1B,IAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,MAAA,IAAI,OAAO,QAAQ,UAAA,EAAY;AAC7B,QAAA,GAAA,CAAI,KAAK,CAAA;AAAA,MACX,CAAA,MAAA,IAAW,GAAA,IAAO,OAAO,GAAA,KAAQ,QAAA,EAAU;AACzC,QAAC,IAA8B,OAAA,GAAU,KAAA;AAAA,MAC3C;AAAA,IACF;AAAA,EACF,CAAA;AACF;AA0BO,SAAS,cACd,WAAA,EACA,QAAA,EACA,KAAA,EACA,OAAA,GAA0B,EAAC,EACb;AACd,EAAA,IAAI,CAAC,cAAA,CAAe,QAAQ,CAAA,EAAG;AAC7B,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,EAAG,WAAW,CAAA,2DAAA,CAA6D,CAAA;AAAA,EAC7F;AAEA,EAAA,MAAM,KAAA,GAAQ,QAAA;AACd,EAAA,MAAM,aAAa,KAAA,CAAM,KAAA;AAEzB,EAAA,MAAM,EAAE,GAAA,EAAK,GAAG,IAAA,EAAK,GAAI,KAAA;AACzB,EAAA,MAAM,MAAA,GAAuB,EAAE,GAAG,IAAA,EAAK;AAEvC,EAAA,IAAI,OAAO,KAAA,CAAM,SAAA,KAAc,YAAY,OAAO,UAAA,CAAW,cAAc,QAAA,EAAU;AACnF,IAAA,MAAA,CAAO,SAAA,GAAY,CAAC,UAAA,CAAW,SAAA,EAAW,KAAA,CAAM,SAAS,CAAA,CAAE,MAAA,CAAO,OAAO,CAAA,CAAE,IAAA,CAAK,GAAG,CAAA;AAAA,EACrF;AAEA,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,OAAO,KAAK,MAAA,CAAO,OAAA,CAAQ,IAAI,CAAA,EAAG;AACjD,IAAA,IAAI,CAAC,GAAA,CAAI,UAAA,CAAW,IAAI,CAAA,IAAK,OAAO,YAAY,UAAA,EAAY;AAC5D,IAAA,IAAI,OAAA,CAAQ,OAAA,EAAS,QAAA,CAAS,GAAG,CAAA,EAAG;AACpC,IAAA,MAAM,MAAA,GAAS,WAAW,GAAG,CAAA;AAC7B,IAAA,IAAI,OAAO,WAAW,UAAA,EAAY;AAElC,IAAA,MAAA,CAAO,GAAG,CAAA,GAAI,CAAC,KAAA,EAAA,GAAmB,IAAA,KAAoB;AACpD,MAAC,MAAA,CAAwC,KAAA,EAAO,GAAG,IAAI,CAAA;AACvD,MAAA,MAAM,YAAa,KAAA,EAAiD,gBAAA;AACpE,MAAA,IAAI,CAAC,SAAA,EAAW;AACd,QAAC,OAAA,CAAyC,KAAA,EAAO,GAAG,IAAI,CAAA;AAAA,MAC1D;AAAA,IACF,CAAA;AAAA,EACF;AAEA,EAAA,IAAI,GAAA,EAAK;AACP,IAAA,MAAA,CAAO,GAAA,GAAM,SAAA,CAAU,GAAA,EAAK,UAAA,CAAW,GAAG,CAAA;AAAA,EAC5C,CAAA,MAAA,IAAW,WAAW,GAAA,EAAK;AACzB,IAAA,MAAA,CAAO,MAAM,UAAA,CAAW,GAAA;AAAA,EAC1B;AAEA,EAAA,OAAO,YAAA,CAAa,OAAO,MAAM,CAAA;AACnC","file":"chunk-ZVDN3GRI.js","sourcesContent":["import { cloneElement, isValidElement, type ReactElement, type ReactNode, type Ref } from 'react';\n\ntype UnknownProps = Record<string, unknown>;\n\n/**\n * Compose two refs into one, so a subcomponent can attach its own ref to a\n * child that already carries the consumer's.\n */\nexport function mergeRefs<T>(...refs: Array<Ref<T> | undefined>): Ref<T> {\n return (value: T | null) => {\n for (const ref of refs) {\n if (typeof ref === 'function') {\n ref(value);\n } else if (ref && typeof ref === 'object') {\n (ref as { current: T | null }).current = value;\n }\n }\n };\n}\n\n/**\n * Shared implementation of the `asChild` pattern.\n *\n * Renders `children` in place of the component's own element, merging our props\n * into it rather than replacing them:\n *\n * - `className` is concatenated, the child's first.\n * - Every `on*` handler is composed: the child's runs first, and ours is skipped\n * if the child called `preventDefault()`. Passing an `onClick` to the child\n * therefore augments the behaviour instead of silently replacing it. Handlers\n * listed in `options.replace` are the exception: ours replaces the child's.\n * - Refs are merged, so a component that needs its own ref does not clobber one\n * the consumer supplied.\n *\n * @param displayName Used in the error message, e.g. 'Modal.Body'.\n */\nexport interface AsChildOptions {\n /**\n * Handlers that replace the child's instead of composing with it. Used when\n * the control is inert: a disabled control must not run the child's handler.\n */\n replace?: readonly string[];\n}\n\nexport function renderAsChild(\n displayName: string,\n children: ReactNode,\n props: UnknownProps,\n options: AsChildOptions = {},\n): ReactElement {\n if (!isValidElement(children)) {\n throw new Error(`${displayName}: asChild requires a single valid React element as children`);\n }\n\n const child = children as ReactElement<UnknownProps & { ref?: Ref<unknown> }>;\n const childProps = child.props;\n // `ref` travels inside props (React 19) and is merged, never read.\n const { ref, ...ours } = props as UnknownProps & { ref?: Ref<unknown> };\n const merged: UnknownProps = { ...ours };\n\n if (typeof props.className === 'string' || typeof childProps.className === 'string') {\n merged.className = [childProps.className, props.className].filter(Boolean).join(' ');\n }\n\n for (const [key, handler] of Object.entries(ours)) {\n if (!key.startsWith('on') || typeof handler !== 'function') continue;\n if (options.replace?.includes(key)) continue;\n const theirs = childProps[key];\n if (typeof theirs !== 'function') continue;\n\n merged[key] = (event: unknown, ...rest: unknown[]) => {\n (theirs as (...args: unknown[]) => void)(event, ...rest);\n const prevented = (event as { defaultPrevented?: boolean } | null)?.defaultPrevented;\n if (!prevented) {\n (handler as (...args: unknown[]) => void)(event, ...rest);\n }\n };\n }\n\n if (ref) {\n merged.ref = mergeRefs(ref, childProps.ref);\n } else if (childProps.ref) {\n merged.ref = childProps.ref;\n }\n\n return cloneElement(child, merged);\n}\n"]}
1
+ {"version":3,"sources":["../src/internal/asChild.ts"],"names":[],"mappings":";;;AAQO,SAAS,aAAgB,IAAA,EAAyC;AACvE,EAAA,OAAO,CAAC,KAAA,KAAoB;AAC1B,IAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,MAAA,IAAI,OAAO,QAAQ,UAAA,EAAY;AAC7B,QAAA,GAAA,CAAI,KAAK,CAAA;AAAA,MACX,CAAA,MAAA,IAAW,GAAA,IAAO,OAAO,GAAA,KAAQ,QAAA,EAAU;AACzC,QAAC,IAA8B,OAAA,GAAU,KAAA;AAAA,MAC3C;AAAA,IACF;AAAA,EACF,CAAA;AACF;AA0BO,SAAS,cACd,WAAA,EACA,QAAA,EACA,KAAA,EACA,OAAA,GAA0B,EAAC,EACb;AACd,EAAA,IAAI,CAAC,cAAA,CAAe,QAAQ,CAAA,EAAG;AAC7B,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,EAAG,WAAW,CAAA,2DAAA,CAA6D,CAAA;AAAA,EAC7F;AAEA,EAAA,MAAM,KAAA,GAAQ,QAAA;AACd,EAAA,MAAM,aAAa,KAAA,CAAM,KAAA;AAEzB,EAAA,MAAM,EAAE,GAAA,EAAK,GAAG,IAAA,EAAK,GAAI,KAAA;AACzB,EAAA,MAAM,MAAA,GAAuB,EAAE,GAAG,IAAA,EAAK;AAEvC,EAAA,IAAI,OAAO,KAAA,CAAM,SAAA,KAAc,YAAY,OAAO,UAAA,CAAW,cAAc,QAAA,EAAU;AACnF,IAAA,MAAA,CAAO,SAAA,GAAY,CAAC,UAAA,CAAW,SAAA,EAAW,KAAA,CAAM,SAAS,CAAA,CAAE,MAAA,CAAO,OAAO,CAAA,CAAE,IAAA,CAAK,GAAG,CAAA;AAAA,EACrF;AAEA,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,OAAO,KAAK,MAAA,CAAO,OAAA,CAAQ,IAAI,CAAA,EAAG;AACjD,IAAA,IAAI,CAAC,GAAA,CAAI,UAAA,CAAW,IAAI,CAAA,IAAK,OAAO,YAAY,UAAA,EAAY;AAC5D,IAAA,IAAI,OAAA,CAAQ,OAAA,EAAS,QAAA,CAAS,GAAG,CAAA,EAAG;AACpC,IAAA,MAAM,MAAA,GAAS,WAAW,GAAG,CAAA;AAC7B,IAAA,IAAI,OAAO,WAAW,UAAA,EAAY;AAElC,IAAA,MAAA,CAAO,GAAG,CAAA,GAAI,CAAC,KAAA,EAAA,GAAmB,IAAA,KAAoB;AACpD,MAAC,MAAA,CAAwC,KAAA,EAAO,GAAG,IAAI,CAAA;AACvD,MAAA,MAAM,YAAa,KAAA,EAAiD,gBAAA;AACpE,MAAA,IAAI,CAAC,SAAA,EAAW;AACd,QAAC,OAAA,CAAyC,KAAA,EAAO,GAAG,IAAI,CAAA;AAAA,MAC1D;AAAA,IACF,CAAA;AAAA,EACF;AAEA,EAAA,IAAI,GAAA,EAAK;AACP,IAAA,MAAA,CAAO,GAAA,GAAM,SAAA,CAAU,GAAA,EAAK,UAAA,CAAW,GAAG,CAAA;AAAA,EAC5C,CAAA,MAAA,IAAW,WAAW,GAAA,EAAK;AACzB,IAAA,MAAA,CAAO,MAAM,UAAA,CAAW,GAAA;AAAA,EAC1B;AAEA,EAAA,OAAO,YAAA,CAAa,OAAO,MAAM,CAAA;AACnC","file":"chunk-QJG5ILK5.js","sourcesContent":["import { cloneElement, isValidElement, type ReactElement, type ReactNode, type Ref } from 'react';\n\ntype UnknownProps = Record<string, unknown>;\n\n/**\n * Compose two refs into one, so a subcomponent can attach its own ref to a\n * child that already carries the consumer's.\n */\nexport function mergeRefs<T>(...refs: Array<Ref<T> | undefined>): Ref<T> {\n return (value: T | null) => {\n for (const ref of refs) {\n if (typeof ref === 'function') {\n ref(value);\n } else if (ref && typeof ref === 'object') {\n (ref as { current: T | null }).current = value;\n }\n }\n };\n}\n\n/**\n * Shared implementation of the `asChild` pattern.\n *\n * Renders `children` in place of the component's own element, merging our props\n * into it rather than replacing them:\n *\n * - `className` is concatenated, the child's first.\n * - Every `on*` handler is composed: the child's runs first, and ours is skipped\n * if the child called `preventDefault()`. Passing an `onClick` to the child\n * therefore augments the behaviour instead of silently replacing it. Handlers\n * listed in `options.replace` are the exception: ours replaces the child's.\n * - Refs are merged, so a component that needs its own ref does not clobber one\n * the consumer supplied.\n *\n * @param displayName Used in the error message, e.g. 'Modal.Body'.\n */\nexport interface AsChildOptions {\n /**\n * Handlers that replace the child's instead of composing with it. Used when\n * the control is inert: a disabled control must not run the child's handler.\n */\n replace?: readonly string[];\n}\n\nexport function renderAsChild(\n displayName: string,\n children: ReactNode,\n props: UnknownProps,\n options: AsChildOptions = {},\n): ReactElement {\n if (!isValidElement(children)) {\n throw new Error(`${displayName}: asChild requires a single valid React element as children`);\n }\n\n const child = children as ReactElement<UnknownProps & { ref?: Ref<unknown> }>;\n const childProps = child.props;\n // `ref` travels inside props (React 19) and is merged, never read.\n const { ref, ...ours } = props as UnknownProps & { ref?: Ref<unknown> };\n const merged: UnknownProps = { ...ours };\n\n if (typeof props.className === 'string' || typeof childProps.className === 'string') {\n merged.className = [childProps.className, props.className].filter(Boolean).join(' ');\n }\n\n for (const [key, handler] of Object.entries(ours)) {\n if (!key.startsWith('on') || typeof handler !== 'function') continue;\n if (options.replace?.includes(key)) continue;\n const theirs = childProps[key];\n if (typeof theirs !== 'function') continue;\n\n merged[key] = (event: unknown, ...rest: unknown[]) => {\n (theirs as (...args: unknown[]) => void)(event, ...rest);\n const prevented = (event as { defaultPrevented?: boolean } | null)?.defaultPrevented;\n if (!prevented) {\n (handler as (...args: unknown[]) => void)(event, ...rest);\n }\n };\n }\n\n if (ref) {\n merged.ref = mergeRefs(ref, childProps.ref);\n } else if (childProps.ref) {\n merged.ref = childProps.ref;\n }\n\n return cloneElement(child, merged);\n}\n"]}
@@ -0,0 +1,43 @@
1
+ import { renderAsChild } from './chunk-QJG5ILK5.js';
2
+ import { classes } from './chunk-MI4QUKQS.js';
3
+ import { useState } from 'react';
4
+ import { jsx } from 'react/jsx-runtime';
5
+
6
+ // src/avatar/Avatar.module.css
7
+ var Avatar_default = {
8
+ root: "Avatar_root",
9
+ image: "Avatar_image"
10
+ };
11
+ function initialsOf(name) {
12
+ const words = (name ?? "").trim().split(/\s+/).filter(Boolean);
13
+ const first = Array.from(words[0] ?? "")[0] ?? "";
14
+ const last = words.length > 1 ? Array.from(words[words.length - 1] ?? "")[0] ?? "" : "";
15
+ return (first + last).toUpperCase();
16
+ }
17
+ function Avatar({ name, src, alt, size = "md", className, ref, children, ...rest }) {
18
+ const source = children ? children : src;
19
+ const [failed, setFailed] = useState(null);
20
+ const showImage = source != null && failed !== source;
21
+ const label = alt ?? name ?? "";
22
+ const decorative = label === "";
23
+ const image = { className: Avatar_default.image, alt: label, onError: () => setFailed(source) };
24
+ return /* @__PURE__ */ jsx(
25
+ "span",
26
+ {
27
+ ...rest,
28
+ ref,
29
+ className: classes(Avatar_default.root, className),
30
+ "data-size": size,
31
+ "data-fallback": showImage ? void 0 : "",
32
+ role: showImage || decorative ? void 0 : "img",
33
+ "aria-label": showImage || decorative ? void 0 : label,
34
+ "aria-hidden": decorative ? true : void 0,
35
+ children: showImage ? children ? renderAsChild("Avatar", children, image) : /* @__PURE__ */ jsx("img", { ...image, src }) : /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: initialsOf(name) })
36
+ }
37
+ );
38
+ }
39
+ Avatar.displayName = "Avatar";
40
+
41
+ export { Avatar };
42
+ //# sourceMappingURL=chunk-QXHSA4QD.js.map
43
+ //# sourceMappingURL=chunk-QXHSA4QD.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/avatar/Avatar.module.css","../src/avatar/Avatar.tsx"],"names":["root","image"],"mappings":";;;;;;AAAA,IAAA,cAAA,GAAA;AAAA,EAKG,IAAA,EAAAA,aAAAA;AAAA,EA0CA,KAAA,EAAAC;AAAA,CAAA;ACpBH,SAAS,WAAW,IAAA,EAA0B;AAC5C,EAAA,MAAM,KAAA,GAAA,CAAS,QAAQ,EAAA,EAAI,IAAA,GAAO,KAAA,CAAM,KAAK,CAAA,CAAE,MAAA,CAAO,OAAO,CAAA;AAC7D,EAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,KAAA,CAAM,CAAC,CAAA,IAAK,EAAE,CAAA,CAAE,CAAC,CAAA,IAAK,EAAA;AAC/C,EAAA,MAAM,IAAA,GAAO,KAAA,CAAM,MAAA,GAAS,CAAA,GAAK,MAAM,IAAA,CAAK,KAAA,CAAM,KAAA,CAAM,MAAA,GAAS,CAAC,CAAA,IAAK,EAAE,CAAA,CAAE,CAAC,KAAK,EAAA,GAAM,EAAA;AACvF,EAAA,OAAA,CAAQ,KAAA,GAAQ,MAAM,WAAA,EAAY;AACpC;AAgBO,SAAS,MAAA,CAAO,EAAE,IAAA,EAAM,GAAA,EAAK,GAAA,EAAK,IAAA,GAAO,IAAA,EAAM,SAAA,EAAW,GAAA,EAAK,QAAA,EAAU,GAAG,IAAA,EAAK,EAAgB;AACtG,EAAA,MAAM,MAAA,GAAS,WAAW,QAAA,GAAW,GAAA;AAErC,EAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAI,SAAkB,IAAI,CAAA;AAClD,EAAA,MAAM,SAAA,GAAY,MAAA,IAAU,IAAA,IAAQ,MAAA,KAAW,MAAA;AAE/C,EAAA,MAAM,KAAA,GAAQ,OAAO,IAAA,IAAQ,EAAA;AAC7B,EAAA,MAAM,aAAa,KAAA,KAAU,EAAA;AAC7B,EAAA,MAAM,KAAA,GAAQ,EAAE,SAAA,EAAW,cAAA,CAAO,KAAA,EAAO,GAAA,EAAK,KAAA,EAAO,OAAA,EAAS,MAAM,SAAA,CAAU,MAAM,CAAA,EAAE;AAEtF,EAAA,uBACE,GAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACE,GAAG,IAAA;AAAA,MACJ,GAAA;AAAA,MACA,SAAA,EAAW,OAAA,CAAQ,cAAA,CAAO,IAAA,EAAM,SAAS,CAAA;AAAA,MACzC,WAAA,EAAW,IAAA;AAAA,MACX,eAAA,EAAe,YAAY,MAAA,GAAY,EAAA;AAAA,MACvC,IAAA,EAAM,SAAA,IAAa,UAAA,GAAa,MAAA,GAAY,KAAA;AAAA,MAC5C,YAAA,EAAY,SAAA,IAAa,UAAA,GAAa,MAAA,GAAY,KAAA;AAAA,MAClD,aAAA,EAAa,aAAa,IAAA,GAAO,MAAA;AAAA,MAEhC,sBACC,QAAA,GACE,aAAA,CAAc,UAAU,QAAA,EAAU,KAAK,oBAEvC,GAAA,CAAC,KAAA,EAAA,EAAK,GAAG,KAAA,EAAO,GAAA,EAAU,oBAG5B,GAAA,CAAC,MAAA,EAAA,EAAK,eAAY,MAAA,EAAQ,QAAA,EAAA,UAAA,CAAW,IAAI,CAAA,EAAE;AAAA;AAAA,GAE/C;AAEJ;AAEA,MAAA,CAAO,WAAA,GAAc,QAAA","file":"chunk-QXHSA4QD.js","sourcesContent":["/* Every value is a token: --avatar-* in packages/tokens/tokens/component/avatar.json */\n\n@layer reset, tokens, vendor, base, components, utilities;\n\n@layer components {\n .root {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n inline-size: var(--avatar-size-md);\n block-size: var(--avatar-size-md);\n overflow: hidden;\n box-sizing: border-box;\n border-radius: var(--avatar-radius);\n background: var(--avatar-bg);\n color: var(--avatar-fg);\n font-family: var(--font-family-body);\n font-size: var(--avatar-font-size-md);\n font-weight: var(--avatar-weight);\n line-height: 1;\n vertical-align: middle;\n\n /* Initials only: a picture has its own edge. */\n &[data-fallback] {\n border: var(--avatar-border-width) solid var(--avatar-border);\n }\n\n &[data-size='sm'] {\n inline-size: var(--avatar-size-sm);\n block-size: var(--avatar-size-sm);\n font-size: var(--avatar-font-size-sm);\n }\n\n &[data-size='lg'] {\n inline-size: var(--avatar-size-lg);\n block-size: var(--avatar-size-lg);\n font-size: var(--avatar-font-size-lg);\n }\n\n &[data-size='xl'] {\n inline-size: var(--avatar-size-xl);\n block-size: var(--avatar-size-xl);\n font-size: var(--avatar-font-size-xl);\n }\n }\n\n .image {\n inline-size: 100%;\n block-size: 100%;\n object-fit: cover;\n }\n}\n","import { useState, type HTMLAttributes, type ReactElement, type Ref } from 'react';\nimport { renderAsChild } from '../internal/asChild';\nimport { classes } from '../internal/classes';\nimport styles from './Avatar.module.css';\n\nexport type AvatarSize = 'sm' | 'md' | 'lg' | 'xl';\n\nexport interface AvatarProps extends Omit<HTMLAttributes<HTMLSpanElement>, 'children'> {\n /** The person's name. Its initials show when there is no image or the image fails, and it names the avatar unless `alt` does. */\n name?: string;\n /** Image URL. Ignored when an image element is passed as the child. */\n src?: string;\n /** Accessible name. Defaults to `name`. Pass `\"\"` next to the visible name, so it is not read twice. */\n alt?: string;\n /** `sm` and `md` match the control heights, so an avatar lines up with a button. @default 'md' */\n size?: AvatarSize;\n /**\n * An image element to use instead of `img`: a framework's image component\n * (`<Avatar name=\"Ana\"><Image src={url} alt=\"\" width={40} height={40} /></Avatar>`).\n * It receives the styles and the error handling; its own `alt` is replaced by the avatar's.\n */\n children?: ReactElement;\n\n ref?: Ref<HTMLSpanElement>;\n}\n\n/** \"Ana María Ruiz\" → \"AR\"; one word → its first letter. By code point, so an accent or an emoji is one character. */\nfunction initialsOf(name: string | undefined) {\n const words = (name ?? '').trim().split(/\\s+/).filter(Boolean);\n const first = Array.from(words[0] ?? '')[0] ?? '';\n const last = words.length > 1 ? (Array.from(words[words.length - 1] ?? '')[0] ?? '') : '';\n return (first + last).toUpperCase();\n}\n\n/**\n * A person, as a picture or as initials. The initials take over when no image\n * is given and when the image fails to load, so a broken URL never shows a\n * broken-image glyph. Every value comes from `--avatar-*` tokens; the\n * background is one token for everyone, not a colour computed from the name.\n *\n * @status experimental\n * @category Utilities\n * @accessibility With an image, the `img` carries the name as its `alt`. With initials, the root is `role=\"img\"` named by `alt` or `name`, and the letters are hidden from assistive technology (\"AR\" read aloud means nothing). `alt=\"\"` makes the avatar decorative (`aria-hidden`): use it when the name is written next to it. Not focusable and not interactive; wrap it in a Link or a Button to make it one.\n * @do Pass `name` always, even with an image: it is the fallback when the image fails.\n * @do Pass `alt=\"\"` when the person's name is visible beside the avatar.\n * @dont Colour avatars per person from a hash of the name; the colours will not be tokens and will not pass contrast in both schemes.\n * @dont Use it for a logo or an illustration; it crops to a circle and falls back to initials.\n */\nexport function Avatar({ name, src, alt, size = 'md', className, ref, children, ...rest }: AvatarProps) {\n const source = children ? children : src;\n // Keyed on what failed, so a new `src` (or a new image element) gets a fresh attempt without an effect.\n const [failed, setFailed] = useState<unknown>(null);\n const showImage = source != null && failed !== source;\n\n const label = alt ?? name ?? '';\n const decorative = label === '';\n const image = { className: styles.image, alt: label, onError: () => setFailed(source) };\n\n return (\n <span\n {...rest}\n ref={ref}\n className={classes(styles.root, className)}\n data-size={size}\n data-fallback={showImage ? undefined : ''}\n role={showImage || decorative ? undefined : 'img'}\n aria-label={showImage || decorative ? undefined : label}\n aria-hidden={decorative ? true : undefined}\n >\n {showImage ? (\n children ? (\n renderAsChild('Avatar', children, image)\n ) : (\n <img {...image} src={src} />\n )\n ) : (\n <span aria-hidden=\"true\">{initialsOf(name)}</span>\n )}\n </span>\n );\n}\n\nAvatar.displayName = 'Avatar';\n"]}
@@ -0,0 +1,106 @@
1
+ import { Field } from './chunk-SXMORGSG.js';
2
+ import { mergeRefs } from './chunk-QJG5ILK5.js';
3
+ import { classes } from './chunk-MI4QUKQS.js';
4
+ import { useRef, useState } from 'react';
5
+ import { Close, Search } from '@pearpages/pulp-icons';
6
+ import { jsx, jsxs } from 'react/jsx-runtime';
7
+
8
+ // src/text-field/TextField.module.css
9
+ var TextField_default = {
10
+ field: "TextField_field",
11
+ input: "TextField_input",
12
+ hiddenLabel: "TextField_hiddenLabel",
13
+ control: "TextField_control",
14
+ inControl: "TextField_inControl",
15
+ icon: "TextField_icon",
16
+ clear: "TextField_clear"
17
+ };
18
+ function TextField({
19
+ label,
20
+ description,
21
+ error,
22
+ hideLabel = false,
23
+ iconStart,
24
+ onClear,
25
+ clearLabel = "Clear",
26
+ size = "md",
27
+ type,
28
+ value,
29
+ defaultValue,
30
+ onChange,
31
+ onKeyDown,
32
+ required,
33
+ disabled,
34
+ readOnly,
35
+ id,
36
+ className,
37
+ ref,
38
+ "aria-describedby": describedBy,
39
+ ...rest
40
+ }) {
41
+ const invalid = error !== void 0 && error !== null && error !== false && error !== "";
42
+ const inner = useRef(null);
43
+ const [ownHasValue, setOwnHasValue] = useState(defaultValue !== void 0 && String(defaultValue) !== "");
44
+ const hasValue = value !== void 0 ? String(value) !== "" : ownHasValue;
45
+ const icon = iconStart === void 0 && type === "search" ? /* @__PURE__ */ jsx(Search, {}) : iconStart;
46
+ const clearable = onClear !== void 0 && hasValue && !disabled && !readOnly;
47
+ const decorated = icon != null || onClear !== void 0;
48
+ const clear = () => {
49
+ if (value === void 0 && inner.current) {
50
+ inner.current.value = "";
51
+ setOwnHasValue(false);
52
+ }
53
+ onClear?.();
54
+ inner.current?.focus();
55
+ };
56
+ const input = /* @__PURE__ */ jsx(Field.Control, { "aria-describedby": describedBy, children: /* @__PURE__ */ jsx(
57
+ "input",
58
+ {
59
+ ...rest,
60
+ ref: mergeRefs(inner, ref),
61
+ type,
62
+ value,
63
+ defaultValue,
64
+ className: classes(TextField_default.input, decorated && TextField_default.inControl),
65
+ readOnly,
66
+ onChange: (event) => {
67
+ onChange?.(event);
68
+ if (value === void 0) setOwnHasValue(event.currentTarget.value !== "");
69
+ },
70
+ onKeyDown: (event) => {
71
+ onKeyDown?.(event);
72
+ if (event.defaultPrevented || event.key !== "Escape" || !clearable) return;
73
+ event.preventDefault();
74
+ event.stopPropagation();
75
+ clear();
76
+ }
77
+ }
78
+ ) });
79
+ return /* @__PURE__ */ jsxs(
80
+ Field,
81
+ {
82
+ id,
83
+ invalid,
84
+ disabled: Boolean(disabled),
85
+ required: Boolean(required),
86
+ className: classes(TextField_default.field, className),
87
+ "data-size": size,
88
+ "data-readonly": readOnly ? "" : void 0,
89
+ children: [
90
+ /* @__PURE__ */ jsx(Field.Label, { className: hideLabel ? TextField_default.hiddenLabel : void 0, children: label }),
91
+ decorated ? /* @__PURE__ */ jsxs("span", { className: TextField_default.control, "data-icon": icon != null ? "" : void 0, "data-clearable": onClear ? "" : void 0, children: [
92
+ input,
93
+ icon != null && /* @__PURE__ */ jsx("span", { className: TextField_default.icon, "aria-hidden": "true", children: icon }),
94
+ clearable && /* @__PURE__ */ jsx("button", { type: "button", className: TextField_default.clear, "aria-label": clearLabel, onClick: clear, children: /* @__PURE__ */ jsx(Close, { "aria-hidden": "true" }) })
95
+ ] }) : input,
96
+ description && /* @__PURE__ */ jsx(Field.Description, { children: description }),
97
+ invalid && /* @__PURE__ */ jsx(Field.Error, { children: error })
98
+ ]
99
+ }
100
+ );
101
+ }
102
+ TextField.displayName = "TextField";
103
+
104
+ export { TextField };
105
+ //# sourceMappingURL=chunk-S632WN4W.js.map
106
+ //# sourceMappingURL=chunk-S632WN4W.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/text-field/TextField.module.css","../src/text-field/TextField.tsx"],"names":["field","input","hiddenLabel","control","inControl","icon","clear"],"mappings":";;;;;;;;AAAA,IAAA,iBAAA,GAAA;AAAA,EASG,KAAA,EAAAA,iBAAAA;AAAA,EAIA,KAAA,EAAAC,iBAAAA;AAAA,EAmDA,WAAA,EAAAC,uBAAAA;AAAA,EAUA,OAAA,EAAAC,mBAAAA;AAAA,EAkBA,SAAA,EAAAC,qBAAAA;AAAA,EAkBA,IAAA,EAAAC,gBAAAA;AAAA,EASA,KAAA,EAAAC;AAAA,CAAA;AC/DI,SAAS,SAAA,CAAU;AAAA,EACxB,KAAA;AAAA,EACA,WAAA;AAAA,EACA,KAAA;AAAA,EACA,SAAA,GAAY,KAAA;AAAA,EACZ,SAAA;AAAA,EACA,OAAA;AAAA,EACA,UAAA,GAAa,OAAA;AAAA,EACb,IAAA,GAAO,IAAA;AAAA,EACP,IAAA;AAAA,EACA,KAAA;AAAA,EACA,YAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,EAAA;AAAA,EACA,SAAA;AAAA,EACA,GAAA;AAAA,EACA,kBAAA,EAAoB,WAAA;AAAA,EACpB,GAAG;AACL,CAAA,EAAmB;AACjB,EAAA,MAAM,UAAU,KAAA,KAAU,MAAA,IAAa,UAAU,IAAA,IAAQ,KAAA,KAAU,SAAS,KAAA,KAAU,EAAA;AACtF,EAAA,MAAM,KAAA,GAAQ,OAAyB,IAAI,CAAA;AAE3C,EAAA,MAAM,CAAC,WAAA,EAAa,cAAc,CAAA,GAAI,QAAA,CAAS,iBAAiB,MAAA,IAAa,MAAA,CAAO,YAAY,CAAA,KAAM,EAAE,CAAA;AACxG,EAAA,MAAM,WAAW,KAAA,KAAU,MAAA,GAAY,MAAA,CAAO,KAAK,MAAM,EAAA,GAAK,WAAA;AAE9D,EAAA,MAAM,OAAO,SAAA,KAAc,MAAA,IAAa,SAAS,QAAA,mBAAW,GAAA,CAAC,UAAO,CAAA,GAAK,SAAA;AACzE,EAAA,MAAM,YAAY,OAAA,KAAY,MAAA,IAAa,QAAA,IAAY,CAAC,YAAY,CAAC,QAAA;AACrE,EAAA,MAAM,SAAA,GAAY,IAAA,IAAQ,IAAA,IAAQ,OAAA,KAAY,MAAA;AAE9C,EAAA,MAAM,QAAQ,MAAM;AAClB,IAAA,IAAI,KAAA,KAAU,MAAA,IAAa,KAAA,CAAM,OAAA,EAAS;AACxC,MAAA,KAAA,CAAM,QAAQ,KAAA,GAAQ,EAAA;AACtB,MAAA,cAAA,CAAe,KAAK,CAAA;AAAA,IACtB;AACA,IAAA,OAAA,IAAU;AACV,IAAA,KAAA,CAAM,SAAS,KAAA,EAAM;AAAA,EACvB,CAAA;AAEA,EAAA,MAAM,wBACJ,GAAA,CAAC,KAAA,CAAM,OAAA,EAAN,EAAc,oBAAkB,WAAA,EAC/B,QAAA,kBAAA,GAAA;AAAA,IAAC,OAAA;AAAA,IAAA;AAAA,MACE,GAAG,IAAA;AAAA,MACJ,GAAA,EAAK,SAAA,CAAU,KAAA,EAAO,GAAG,CAAA;AAAA,MACzB,IAAA;AAAA,MACA,KAAA;AAAA,MACA,YAAA;AAAA,MACA,WAAW,OAAA,CAAQ,iBAAA,CAAO,KAAA,EAAO,SAAA,IAAa,kBAAO,SAAS,CAAA;AAAA,MAC9D,QAAA;AAAA,MACA,QAAA,EAAU,CAAC,KAAA,KAAU;AACnB,QAAA,QAAA,GAAW,KAAK,CAAA;AAChB,QAAA,IAAI,UAAU,MAAA,EAAW,cAAA,CAAe,KAAA,CAAM,aAAA,CAAc,UAAU,EAAE,CAAA;AAAA,MAC1E,CAAA;AAAA,MACA,SAAA,EAAW,CAAC,KAAA,KAAU;AACpB,QAAA,SAAA,GAAY,KAAK,CAAA;AACjB,QAAA,IAAI,MAAM,gBAAA,IAAoB,KAAA,CAAM,GAAA,KAAQ,QAAA,IAAY,CAAC,SAAA,EAAW;AAEpE,QAAA,KAAA,CAAM,cAAA,EAAe;AACrB,QAAA,KAAA,CAAM,eAAA,EAAgB;AACtB,QAAA,KAAA,EAAM;AAAA,MACR;AAAA;AAAA,GACF,EACF,CAAA;AAGF,EAAA,uBACE,IAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,EAAA;AAAA,MACA,OAAA;AAAA,MACA,QAAA,EAAU,QAAQ,QAAQ,CAAA;AAAA,MAC1B,QAAA,EAAU,QAAQ,QAAQ,CAAA;AAAA,MAC1B,SAAA,EAAW,OAAA,CAAQ,iBAAA,CAAO,KAAA,EAAO,SAAS,CAAA;AAAA,MAC1C,WAAA,EAAW,IAAA;AAAA,MACX,eAAA,EAAe,WAAW,EAAA,GAAK,MAAA;AAAA,MAE/B,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,KAAA,CAAM,OAAN,EAAY,SAAA,EAAW,YAAY,iBAAA,CAAO,WAAA,GAAc,QAAY,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,QAC1E,SAAA,mBACC,IAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAW,kBAAO,OAAA,EAAS,WAAA,EAAW,IAAA,IAAQ,IAAA,GAAO,EAAA,GAAK,MAAA,EAAW,gBAAA,EAAgB,OAAA,GAAU,KAAK,MAAA,EACvG,QAAA,EAAA;AAAA,UAAA,KAAA;AAAA,UAEA,IAAA,IAAQ,wBACP,GAAA,CAAC,MAAA,EAAA,EAAK,WAAW,iBAAA,CAAO,IAAA,EAAM,aAAA,EAAY,MAAA,EACvC,QAAA,EAAA,IAAA,EACH,CAAA;AAAA,UAED,6BACC,GAAA,CAAC,QAAA,EAAA,EAAO,IAAA,EAAK,QAAA,EAAS,WAAW,iBAAA,CAAO,KAAA,EAAO,YAAA,EAAY,UAAA,EAAY,SAAS,KAAA,EAC9E,QAAA,kBAAA,GAAA,CAAC,KAAA,EAAA,EAAM,aAAA,EAAY,QAAO,CAAA,EAC5B;AAAA,SAAA,EAEJ,CAAA,GAEA,KAAA;AAAA,QAED,WAAA,oBAAe,GAAA,CAAC,KAAA,CAAM,WAAA,EAAN,EAAmB,QAAA,EAAA,WAAA,EAAY,CAAA;AAAA,QAC/C,OAAA,oBAAW,GAAA,CAAC,KAAA,CAAM,KAAA,EAAN,EAAa,QAAA,EAAA,KAAA,EAAM;AAAA;AAAA;AAAA,GAClC;AAEJ;AAEA,SAAA,CAAU,WAAA,GAAc,WAAA","file":"chunk-S632WN4W.js","sourcesContent":["/*\n * The input's own styles (--text-field-*). Label, description and error come\n * from Field. State lives on the wrapper as data attributes and on the input\n * as native pseudo-classes.\n */\n\n@layer reset, tokens, vendor, base, components, utilities;\n\n@layer components {\n .field {\n font-family: var(--text-field-font-family);\n }\n\n .input {\n min-block-size: var(--text-field-height-md);\n padding-block: 0;\n padding-inline: var(--text-field-padding-inline);\n border: 1px solid var(--text-field-border-default);\n border-radius: var(--text-field-radius);\n background-color: var(--text-field-bg);\n color: var(--text-field-fg);\n font-size: var(--text-field-font-size-md);\n transition:\n border-color var(--text-field-motion-duration) var(--motion-easing-standard),\n background-color var(--text-field-motion-duration) var(--motion-easing-standard);\n\n &::placeholder {\n color: var(--text-field-placeholder);\n }\n\n &:focus-visible {\n border-color: var(--text-field-border-focus);\n outline: var(--text-field-focus-ring-width) solid var(--text-field-focus-ring);\n outline-offset: var(--text-field-focus-ring-offset);\n }\n\n &:disabled {\n cursor: not-allowed;\n opacity: 0.55;\n }\n\n &:read-only:not(:disabled) {\n background-color: var(--color-surface-sunken);\n }\n\n &:hover:not(:disabled, :focus-visible) {\n border-color: var(--text-field-border-hover);\n }\n }\n\n .field[data-size=\"sm\"] .input {\n min-block-size: var(--text-field-height-sm);\n font-size: var(--text-field-font-size-sm);\n }\n\n .field[data-size=\"lg\"] .input {\n min-block-size: var(--text-field-height-lg);\n font-size: var(--text-field-font-size-lg);\n }\n\n .field[data-invalid] .input {\n border-color: var(--text-field-border-invalid);\n }\n\n .hiddenLabel {\n position: absolute;\n inline-size: var(--size-hairline);\n block-size: var(--size-hairline);\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n }\n\n /* Only when there is an icon or a clear button: the input keeps its own box, they sit over its padding. */\n .control {\n --_slot: var(--text-field-height-md);\n\n display: grid;\n position: relative;\n align-items: center;\n\n .field[data-size=\"sm\"] & {\n --_slot: var(--text-field-height-sm);\n }\n\n .field[data-size=\"lg\"] & {\n --_slot: var(--text-field-height-lg);\n }\n\n }\n\n /* The input inside .control: a class of its own, so these rules do not race the .input states above. */\n .inControl {\n grid-area: 1 / 1;\n inline-size: 100%;\n\n /* The browser's own clear control would be a second, unnamed one. */\n &::-webkit-search-cancel-button {\n display: none;\n }\n }\n\n .control[data-icon] .inControl {\n padding-inline-start: calc(var(--text-field-padding-inline) + 1em + var(--text-field-icon-gap));\n }\n\n .control[data-clearable] .inControl {\n padding-inline-end: var(--_slot);\n }\n\n .icon {\n display: inline-flex;\n grid-area: 1 / 1;\n justify-self: start;\n margin-inline-start: var(--text-field-padding-inline);\n color: var(--text-field-icon-fg);\n pointer-events: none;\n }\n\n .clear {\n display: inline-flex;\n grid-area: 1 / 1;\n align-items: center;\n justify-content: center;\n justify-self: end;\n inline-size: var(--_slot);\n block-size: var(--_slot);\n padding: 0;\n border: 0;\n border-radius: var(--text-field-radius);\n background: transparent;\n color: var(--text-field-icon-fg);\n cursor: pointer;\n\n &:hover {\n color: var(--text-field-icon-fg-hover);\n }\n\n &:focus-visible {\n outline: var(--text-field-focus-ring-width) solid var(--text-field-focus-ring);\n outline-offset: calc(-1 * var(--text-field-focus-ring-width));\n }\n }\n}\n","import { useRef, useState, type InputHTMLAttributes, type ReactNode, type Ref } from 'react';\nimport { Close, Search } from '@pearpages/pulp-icons';\nimport { Field } from '../field';\nimport { mergeRefs } from '../internal/asChild';\nimport { classes } from '../internal/classes';\nimport styles from './TextField.module.css';\n\nexport type TextFieldSize = 'sm' | 'md' | 'lg';\n\nexport interface TextFieldProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'size'> {\n /** Visible label. Always rendered: a placeholder is not a label. */\n label: ReactNode;\n /** Help text under the field, exposed as the input's accessible description. */\n description?: ReactNode;\n /**\n * Error message. Its presence marks the input invalid (`aria-invalid`,\n * `data-invalid`) and the message is announced as an alert.\n */\n error?: ReactNode;\n /** Keeps the label for assistive technology only. For a search box that a heading or its place in the page already names. @default false */\n hideLabel?: boolean;\n /** A decorative glyph inside the field, before the text. `type=\"search\"` gets the Search glyph unless you pass another (or `null`). */\n iconStart?: ReactNode;\n /**\n * Adds a clear button that appears once the field has a value. Called when it\n * is pressed and when Escape is pressed with a value. Controlled: set your\n * value to `''` here. Uncontrolled: the input is emptied for you.\n */\n onClear?: () => void;\n /** The clear button's name, for other languages. @default 'Clear' */\n clearLabel?: string;\n /** @default 'md' */\n size?: TextFieldSize;\n /** The `<input>` element. */\n ref?: Ref<HTMLInputElement>;\n /** Applied to the wrapper, not the input. */\n className?: string;\n}\n\n/**\n * A single-line text input on top of `Field`: label, description and error\n * wired for assistive technology. Controlled and uncontrolled behave exactly\n * like the native input (`value`/`onChange` or `defaultValue`). Every value\n * comes from `--text-field-*` and `--field-*` tokens; state is exposed as\n * `data-size`, `data-invalid`, `data-disabled` and `data-readonly` on the\n * wrapper.\n *\n * @status stable\n * @category Forms\n * @accessibility A native text `input` wired through Field: `label[for]`, `aria-describedby` for description and error, `aria-invalid` and `aria-required`. Everything the browser gives a native input (autofill, IME, forms) applies. `hideLabel` hides the label visually, never from assistive technology. The leading icon is decorative. The clear button is a real `button` named by `clearLabel`, after the input in the tab order, present only while there is a value; pressing it (or Escape in the field) empties the field and leaves focus in the input. `type=\"search\"` gives the input the `searchbox` role; wrap the form in `<search>` or `role=\"search\"` yourself when it is the page's search.\n * @do Always pass `label`; use a visible one.\n * Prefer `error` text that says how to fix the value.\n * @do For a search box: `type=\"search\"`, `hideLabel` if a heading names it, and `onClear`.\n * @dont Use `placeholder` as the label.\n * Use it for multi-line text; use Textarea.\n */\nexport function TextField({\n label,\n description,\n error,\n hideLabel = false,\n iconStart,\n onClear,\n clearLabel = 'Clear',\n size = 'md',\n type,\n value,\n defaultValue,\n onChange,\n onKeyDown,\n required,\n disabled,\n readOnly,\n id,\n className,\n ref,\n 'aria-describedby': describedBy,\n ...rest\n}: TextFieldProps) {\n const invalid = error !== undefined && error !== null && error !== false && error !== '';\n const inner = useRef<HTMLInputElement>(null);\n // Uncontrolled: remember whether there is text, so the clear button can come and go.\n const [ownHasValue, setOwnHasValue] = useState(defaultValue !== undefined && String(defaultValue) !== '');\n const hasValue = value !== undefined ? String(value) !== '' : ownHasValue;\n\n const icon = iconStart === undefined && type === 'search' ? <Search /> : iconStart;\n const clearable = onClear !== undefined && hasValue && !disabled && !readOnly;\n const decorated = icon != null || onClear !== undefined;\n\n const clear = () => {\n if (value === undefined && inner.current) {\n inner.current.value = '';\n setOwnHasValue(false);\n }\n onClear?.();\n inner.current?.focus();\n };\n\n const input = (\n <Field.Control aria-describedby={describedBy}>\n <input\n {...rest}\n ref={mergeRefs(inner, ref)}\n type={type}\n value={value}\n defaultValue={defaultValue}\n className={classes(styles.input, decorated && styles.inControl)}\n readOnly={readOnly}\n onChange={(event) => {\n onChange?.(event);\n if (value === undefined) setOwnHasValue(event.currentTarget.value !== '');\n }}\n onKeyDown={(event) => {\n onKeyDown?.(event);\n if (event.defaultPrevented || event.key !== 'Escape' || !clearable) return;\n // Handled here, so a dialog around the field does not also close on this Escape.\n event.preventDefault();\n event.stopPropagation();\n clear();\n }}\n />\n </Field.Control>\n );\n\n return (\n <Field\n id={id}\n invalid={invalid}\n disabled={Boolean(disabled)}\n required={Boolean(required)}\n className={classes(styles.field, className)}\n data-size={size}\n data-readonly={readOnly ? '' : undefined}\n >\n <Field.Label className={hideLabel ? styles.hiddenLabel : undefined}>{label}</Field.Label>\n {decorated ? (\n <span className={styles.control} data-icon={icon != null ? '' : undefined} data-clearable={onClear ? '' : undefined}>\n {input}\n {/* After the input in the DOM: they share a grid cell, and the input's background would paint over it. */}\n {icon != null && (\n <span className={styles.icon} aria-hidden=\"true\">\n {icon}\n </span>\n )}\n {clearable && (\n <button type=\"button\" className={styles.clear} aria-label={clearLabel} onClick={clear}>\n <Close aria-hidden=\"true\" />\n </button>\n )}\n </span>\n ) : (\n input\n )}\n {description && <Field.Description>{description}</Field.Description>}\n {invalid && <Field.Error>{error}</Field.Error>}\n </Field>\n );\n}\n\nTextField.displayName = 'TextField';\n"]}
@@ -1,6 +1,6 @@
1
1
  import { useDismiss } from './chunk-NAYFLTK6.js';
2
2
  import { useFloatingPosition } from './chunk-U6QRAD73.js';
3
- import { renderAsChild } from './chunk-ZVDN3GRI.js';
3
+ import { renderAsChild } from './chunk-QJG5ILK5.js';
4
4
  import { classes } from './chunk-MI4QUKQS.js';
5
5
  import { createContext, useState, useCallback, useId, useRef, useEffect, useContext } from 'react';
6
6
  import { createPortal } from 'react-dom';
@@ -125,5 +125,5 @@ Popover.Content = PopoverContent;
125
125
  Popover.Close = PopoverClose;
126
126
 
127
127
  export { Popover };
128
- //# sourceMappingURL=chunk-OFFFRIJG.js.map
129
- //# sourceMappingURL=chunk-OFFFRIJG.js.map
128
+ //# sourceMappingURL=chunk-SDIK6VSC.js.map
129
+ //# sourceMappingURL=chunk-SDIK6VSC.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/popover/Popover.module.css","../src/popover/Popover.tsx"],"names":["content","title"],"mappings":";;;;;;;;;AAAA,IAAA,eAAA,GAAA;AAAA,EAKG,OAAA,EAAAA,iBAAAA;AAAA,EA2BA,KAAA,EAAAC;AAAA,CAAA;ACDH,IAAM,cAAA,GAAiB,cAA0C,IAAI,CAAA;AAErE,SAAS,WAAW,IAAA,EAAmC;AACrD,EAAA,MAAM,OAAA,GAAU,WAAW,cAAc,CAAA;AACzC,EAAA,IAAI,CAAC,OAAA,EAAS,MAAM,IAAI,KAAA,CAAM,CAAA,EAAG,IAAI,CAAA,kCAAA,CAAoC,CAAA;AACzE,EAAA,OAAO,OAAA;AACT;AA4BO,SAAS,OAAA,CAAQ,EAAE,IAAA,EAAM,WAAA,GAAc,OAAO,YAAA,EAAc,SAAA,GAAY,cAAA,EAAgB,QAAA,EAAS,EAAiB;AACvH,EAAA,MAAM,CAAC,YAAA,EAAc,eAAe,CAAA,GAAI,SAAS,WAAW,CAAA;AAC5D,EAAA,MAAM,aAAa,IAAA,KAAS,MAAA;AAC5B,EAAA,MAAM,MAAA,GAAS,aAAa,IAAA,GAAO,YAAA;AACnC,EAAA,MAAM,OAAA,GAAU,WAAA;AAAA,IACd,CAAC,IAAA,KAAkB;AACjB,MAAA,IAAI,CAAC,UAAA,EAAY,eAAA,CAAgB,IAAI,CAAA;AACrC,MAAA,YAAA,GAAe,IAAI,CAAA;AAAA,IACrB,CAAA;AAAA,IACA,CAAC,YAAY,YAAY;AAAA,GAC3B;AACA,EAAA,MAAM,KAAK,KAAA,EAAM;AACjB,EAAA,MAAM,WAAW,mBAAA,CAAoB,EAAE,IAAA,EAAM,MAAA,EAAQ,WAAW,CAAA;AAEhE,EAAA,uBACE,GAAA,CAAC,eAAe,QAAA,EAAf,EAAwB,OAAO,EAAE,IAAA,EAAM,QAAQ,OAAA,EAAS,SAAA,EAAW,GAAG,EAAE,CAAA,QAAA,CAAA,EAAY,SAAS,CAAA,EAAG,EAAE,UAAU,SAAA,EAAW,QAAA,IACrH,QAAA,EACH,CAAA;AAEJ;AASA,SAAS,cAAA,CAAe,EAAE,OAAA,GAAU,KAAA,EAAO,SAAS,GAAA,EAAK,QAAA,EAAU,GAAG,IAAA,EAAK,EAAwB;AACjG,EAAA,MAAM,OAAA,GAAU,WAAW,iBAAiB,CAAA;AAC5C,EAAA,MAAM,KAAA,GAAQ;AAAA,IACZ,GAAG,IAAA;AAAA,IACH,GAAA,EAAK,OAAA,CAAQ,QAAA,CAAS,IAAA,CAAK,YAAA;AAAA,IAC3B,eAAA,EAAiB,QAAA;AAAA,IACjB,iBAAiB,OAAA,CAAQ,IAAA;AAAA,IACzB,eAAA,EAAiB,OAAA,CAAQ,IAAA,GAAO,OAAA,CAAQ,SAAA,GAAY,MAAA;AAAA,IACpD,OAAA,EAAS,CAAC,KAAA,KAA+C;AACvD,MAAA,OAAA,GAAU,KAAK,CAAA;AACf,MAAA,IAAI,CAAC,KAAA,CAAM,gBAAA,UAA0B,OAAA,CAAQ,CAAC,QAAQ,IAAI,CAAA;AAAA,IAC5D;AAAA,GACF;AACA,EAAA,IAAI,OAAA,EAAS;AAEX,IAAA,OAAO,aAAA,CAAc,iBAAA,EAAmB,QAAA,EAAU,EAAE,GAAG,KAAA,EAAO,GAAA,EAAK,SAAA,CAAU,GAAA,EAAK,OAAA,CAAQ,QAAA,CAAS,IAAA,CAAK,YAAY,GAAG,CAAA;AAAA,EACzH;AACA,EAAA,uBACE,GAAA,CAAC,QAAA,EAAA,EAAO,IAAA,EAAK,QAAA,EAAU,GAAG,KAAA,EAAO,GAAA,EAAK,SAAA,CAAU,GAAA,EAAK,OAAA,CAAQ,QAAA,CAAS,IAAA,CAAK,YAAY,GACpF,QAAA,EACH,CAAA;AAEJ;AAEA,SAAS,SAAA,CAAa,GAAuB,CAAA,EAA6B;AACxE,EAAA,OAAO,CAAC,IAAA,KAAmB;AACzB,IAAA,CAAA,CAAE,IAAI,CAAA;AACN,IAAA,IAAI,OAAO,CAAA,KAAM,UAAA,EAAY,CAAA,CAAE,IAAI,CAAA;AAAA,SAAA,IAC1B,CAAA,IAAK,OAAA,GAAU,IAAA;AAAA,EAC1B,CAAA;AACF;AASA,SAAS,cAAA,CAAe,EAAE,KAAA,EAAO,SAAA,EAAW,KAAK,QAAA,EAAU,GAAG,MAAK,EAAwB;AACzF,EAAA,MAAM,OAAA,GAAU,WAAW,iBAAiB,CAAA;AAC5C,EAAA,MAAM,EAAE,IAAA,EAAM,aAAA,EAAe,SAAA,KAAc,OAAA,CAAQ,QAAA;AACnD,EAAA,MAAM,UAAA,GAAa,OAA8B,IAAI,CAAA;AAErD,EAAA,UAAA,CAAW;AAAA,IACT,MAAM,OAAA,CAAQ,IAAA;AAAA,IACd,SAAA,EAAW,MAAM,OAAA,CAAQ,OAAA,CAAQ,KAAK,CAAA;AAAA,IACtC,MAAA,EAAQ,MAAM,CAAC,IAAA,CAAK,UAAU,OAAA,EAA2B,IAAA,CAAK,SAAS,OAAO;AAAA,GAC/E,CAAA;AAGD,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,QAAQ,IAAA,EAAM;AAChB,MAAA,MAAM,UAAU,UAAA,CAAW,OAAA;AAC3B,MAAA,IAAI,CAAC,OAAA,EAAS;AACd,MAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,aAAA,CAA2B,2EAA2E,CAAA;AAC5H,MAAA,CAAC,KAAA,IAAS,SAAS,KAAA,EAAM;AACzB,MAAA,OAAO,MAAM;AACX,QAAA,MAAM,SAAA,GAAY,KAAK,SAAA,CAAU,OAAA;AACjC,QAAA,IAAI,OAAA,CAAQ,QAAA,CAAS,QAAA,CAAS,aAAa,CAAA,IAAK,SAAS,aAAA,KAAkB,QAAA,CAAS,IAAA,EAAM,SAAA,EAAW,KAAA,EAAM;AAAA,MAC7G,CAAA;AAAA,IACF;AAAA,EACF,GAAG,CAAC,OAAA,CAAQ,IAAA,EAAM,IAAA,CAAK,SAAS,CAAC,CAAA;AAEjC,EAAA,IAAI,CAAC,OAAA,CAAQ,IAAA,EAAM,OAAO,IAAA;AAC1B,EAAA,OAAO,YAAA;AAAA,oBACL,IAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACE,GAAG,IAAA;AAAA,QACJ,GAAA,EAAK,SAAA,CAAU,GAAA,EAAK,CAAC,IAAA,KAAS;AAC5B,UAAA,UAAA,CAAW,OAAA,GAAU,IAAA;AACrB,UAAA,IAAA,CAAK,YAAY,IAAI,CAAA;AAAA,QACvB,CAAC,CAAA;AAAA,QACD,IAAI,OAAA,CAAQ,SAAA;AAAA,QACZ,IAAA,EAAK,QAAA;AAAA,QACL,iBAAA,EAAiB,KAAA,GAAQ,OAAA,CAAQ,OAAA,GAAU,MAAA;AAAA,QAC3C,QAAA,EAAU,EAAA;AAAA,QACV,SAAA,EAAW,OAAA,CAAQ,eAAA,CAAO,OAAA,EAAS,SAAS,CAAA;AAAA,QAC5C,gBAAA,EAAgB,SAAA;AAAA,QAEhB,KAAA,EAAO,aAAA;AAAA,QAEN,QAAA,EAAA;AAAA,UAAA,KAAA,oBACC,GAAA,CAAC,QAAG,EAAA,EAAI,OAAA,CAAQ,SAAS,SAAA,EAAW,eAAA,CAAO,OACxC,QAAA,EAAA,KAAA,EACH,CAAA;AAAA,UAED;AAAA;AAAA;AAAA,KACH;AAAA,IACA,QAAA,CAAS;AAAA,GACX;AACF;AAOA,SAAS,YAAA,CAAa,EAAE,OAAA,GAAU,KAAA,EAAO,SAAS,QAAA,EAAU,GAAG,MAAK,EAAsB;AACxF,EAAA,MAAM,OAAA,GAAU,WAAW,eAAe,CAAA;AAC1C,EAAA,MAAM,KAAA,GAAQ;AAAA,IACZ,GAAG,IAAA;AAAA,IACH,OAAA,EAAS,CAAC,KAAA,KAA+C;AACvD,MAAA,OAAA,GAAU,KAAK,CAAA;AACf,MAAA,IAAI,CAAC,KAAA,CAAM,gBAAA,EAAkB,OAAA,CAAQ,QAAQ,KAAK,CAAA;AAAA,IACpD;AAAA,GACF;AACA,EAAA,IAAI,OAAA,EAAS,OAAO,aAAA,CAAc,eAAA,EAAiB,UAAU,KAAK,CAAA;AAClE,EAAA,2BACG,QAAA,EAAA,EAAO,IAAA,EAAK,QAAA,EAAU,GAAG,OACvB,QAAA,EACH,CAAA;AAEJ;AAEA,OAAA,CAAQ,WAAA,GAAc,SAAA;AACtB,cAAA,CAAe,WAAA,GAAc,iBAAA;AAC7B,cAAA,CAAe,WAAA,GAAc,iBAAA;AAC7B,YAAA,CAAa,WAAA,GAAc,eAAA;AAE3B,OAAA,CAAQ,OAAA,GAAU,cAAA;AAClB,OAAA,CAAQ,OAAA,GAAU,cAAA;AAClB,OAAA,CAAQ,KAAA,GAAQ,YAAA","file":"chunk-OFFFRIJG.js","sourcesContent":["/* Every value is a token (--popover-*). Position comes in as --_x/--_y from the floating hook. */\n\n@layer reset, tokens, vendor, base, components, utilities;\n\n@layer components {\n .content {\n --_gap: var(--popover-gap);\n\n position: fixed;\n z-index: var(--popover-layer);\n inset-block-start: var(--_y);\n inset-inline-start: var(--_x);\n display: flex;\n flex-direction: column;\n gap: var(--popover-gap);\n inline-size: var(--popover-width);\n max-inline-size: calc(100vw - 2 * var(--space-4));\n padding: var(--popover-padding);\n border: var(--size-hairline) solid var(--popover-border);\n border-radius: var(--popover-radius);\n background-color: var(--popover-bg);\n color: var(--popover-fg);\n font-family: var(--font-family-body);\n box-shadow: var(--popover-shadow);\n animation: fade var(--popover-duration) var(--motion-easing-standard);\n\n &:focus-visible {\n outline: var(--popover-focus-ring-width) solid var(--popover-focus-ring);\n outline-offset: var(--popover-focus-ring-offset);\n }\n }\n\n .title {\n margin: 0;\n font-family: var(--font-family-display);\n font-size: var(--font-size-md);\n font-weight: var(--font-weight-semibold);\n line-height: var(--font-line-height-tight);\n }\n\n @keyframes fade {\n from {\n opacity: 0;\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n .content {\n animation: none;\n }\n }\n}\n","import {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useId,\n useRef,\n useState,\n type ButtonHTMLAttributes,\n type HTMLAttributes,\n type ReactNode,\n type Ref,\n} from 'react';\nimport { createPortal } from 'react-dom';\nimport { renderAsChild } from '../internal/asChild';\nimport { classes } from '../internal/classes';\nimport { useFloatingPosition, type FloatingPlacement } from '../internal/floating';\nimport { useDismiss } from '../internal/useDismiss';\nimport styles from './Popover.module.css';\n\nexport type PopoverPlacement = FloatingPlacement;\n\ninterface PopoverContextValue {\n open: boolean;\n setOpen: (open: boolean) => void;\n contentId: string;\n titleId: string;\n placement: PopoverPlacement;\n floating: ReturnType<typeof useFloatingPosition>;\n}\n\nconst PopoverContext = createContext<PopoverContextValue | null>(null);\n\nfunction usePopover(part: string): PopoverContextValue {\n const context = useContext(PopoverContext);\n if (!context) throw new Error(`${part} must be rendered inside <Popover>`);\n return context;\n}\n\nexport interface PopoverProps {\n /** Controlled open state. */\n open?: boolean;\n /** @default false */\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n /** Preferred side; flips when there is no room. @default 'bottom-start' */\n placement?: PopoverPlacement;\n children: ReactNode;\n}\n\n/**\n * A non-modal layer anchored to its trigger: a small form, a filter, a\n * detail panel. The page stays interactive; Escape, a click outside or\n * `Popover.Close` dismiss it and focus returns to the trigger. Compose with\n * `Popover.Trigger`, `Popover.Content` and `Popover.Close`. For anything that\n * must block the page, use Dialog.\n *\n * @status stable\n * @category Overlays\n * @accessibility A non-modal `role=\"dialog\"` named by `title` (or `aria-label`); the trigger has `aria-haspopup=\"dialog\"` and `aria-expanded`. Focus moves to the first focusable element on open and back to the trigger on close; Escape and a click outside dismiss it.\n * @do Give it a `title` or `aria-label`.\n * Use `Popover.Close` inside forms so a keyboard user has a clear exit.\n * @dont Put a long form or a destructive confirmation in it; use Dialog.\n * Open it on hover; that is Tooltip.\n */\nexport function Popover({ open, defaultOpen = false, onOpenChange, placement = 'bottom-start', children }: PopoverProps) {\n const [uncontrolled, setUncontrolled] = useState(defaultOpen);\n const controlled = open !== undefined;\n const isOpen = controlled ? open : uncontrolled;\n const setOpen = useCallback(\n (next: boolean) => {\n if (!controlled) setUncontrolled(next);\n onOpenChange?.(next);\n },\n [controlled, onOpenChange],\n );\n const id = useId();\n const floating = useFloatingPosition({ open: isOpen, placement });\n\n return (\n <PopoverContext.Provider value={{ open: isOpen, setOpen, contentId: `${id}-content`, titleId: `${id}-title`, placement, floating }}>\n {children}\n </PopoverContext.Provider>\n );\n}\n\ninterface PopoverTriggerProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n /** Render the child element as the trigger instead of a plain button. @default false */\n asChild?: boolean;\n ref?: Ref<HTMLButtonElement>;\n children: ReactNode;\n}\n\nfunction PopoverTrigger({ asChild = false, onClick, ref, children, ...rest }: PopoverTriggerProps) {\n const popover = usePopover('Popover.Trigger');\n const props = {\n ...rest,\n ref: popover.floating.refs.setReference,\n 'aria-haspopup': 'dialog' as const,\n 'aria-expanded': popover.open,\n 'aria-controls': popover.open ? popover.contentId : undefined,\n onClick: (event: React.MouseEvent<HTMLButtonElement>) => {\n onClick?.(event);\n if (!event.defaultPrevented) popover.setOpen(!popover.open);\n },\n };\n if (asChild) {\n // eslint-disable-next-line react-hooks/refs -- forwarded to the reference element, not read\n return renderAsChild('Popover.Trigger', children, { ...props, ref: mergeRefs(ref, popover.floating.refs.setReference) });\n }\n return (\n <button type=\"button\" {...props} ref={mergeRefs(ref, popover.floating.refs.setReference)}>\n {children}\n </button>\n );\n}\n\nfunction mergeRefs<T>(a: Ref<T> | undefined, b: (node: T | null) => void) {\n return (node: T | null) => {\n b(node);\n if (typeof a === 'function') a(node);\n else if (a) a.current = node;\n };\n}\n\ninterface PopoverContentProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {\n /** Rendered as the dialog's heading and used as its accessible name. Otherwise pass `aria-label`. */\n title?: ReactNode;\n ref?: Ref<HTMLDivElement>;\n children: ReactNode;\n}\n\nfunction PopoverContent({ title, className, ref, children, ...rest }: PopoverContentProps) {\n const popover = usePopover('Popover.Content');\n const { refs, positionStyle, placement } = popover.floating;\n const contentRef = useRef<HTMLDivElement | null>(null);\n\n useDismiss({\n open: popover.open,\n onDismiss: () => popover.setOpen(false),\n inside: () => [refs.reference.current as Element | null, refs.floating.current],\n });\n\n // Move focus in on open; give it back to the trigger on close.\n useEffect(() => {\n if (popover.open) {\n const content = contentRef.current;\n if (!content) return;\n const first = content.querySelector<HTMLElement>('input, select, textarea, button, a[href], [tabindex]:not([tabindex=\"-1\"])');\n (first ?? content).focus();\n return () => {\n const reference = refs.reference.current as HTMLElement | null;\n if (content.contains(document.activeElement) || document.activeElement === document.body) reference?.focus();\n };\n }\n }, [popover.open, refs.reference]);\n\n if (!popover.open) return null;\n return createPortal(\n <div\n {...rest}\n ref={mergeRefs(ref, (node) => {\n contentRef.current = node;\n refs.setFloating(node);\n })}\n id={popover.contentId}\n role=\"dialog\"\n aria-labelledby={title ? popover.titleId : undefined}\n tabIndex={-1}\n className={classes(styles.content, className)}\n data-placement={placement}\n // eslint-disable-next-line react/forbid-dom-props -- per-instance position (--_x/--_y), see internal/floating.ts\n style={positionStyle}\n >\n {title && (\n <h2 id={popover.titleId} className={styles.title}>\n {title}\n </h2>\n )}\n {children}\n </div>,\n document.body,\n );\n}\n\ninterface PopoverCloseProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n asChild?: boolean;\n children: ReactNode;\n}\n\nfunction PopoverClose({ asChild = false, onClick, children, ...rest }: PopoverCloseProps) {\n const popover = usePopover('Popover.Close');\n const props = {\n ...rest,\n onClick: (event: React.MouseEvent<HTMLButtonElement>) => {\n onClick?.(event);\n if (!event.defaultPrevented) popover.setOpen(false);\n },\n };\n if (asChild) return renderAsChild('Popover.Close', children, props);\n return (\n <button type=\"button\" {...props}>\n {children}\n </button>\n );\n}\n\nPopover.displayName = 'Popover';\nPopoverTrigger.displayName = 'Popover.Trigger';\nPopoverContent.displayName = 'Popover.Content';\nPopoverClose.displayName = 'Popover.Close';\n\nPopover.Trigger = PopoverTrigger;\nPopover.Content = PopoverContent;\nPopover.Close = PopoverClose;\n"]}
1
+ {"version":3,"sources":["../src/popover/Popover.module.css","../src/popover/Popover.tsx"],"names":["content","title"],"mappings":"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","file":"chunk-SDIK6VSC.js","sourcesContent":["/* Every value is a token (--popover-*). Position comes in as --_x/--_y from the floating hook. */\n\n@layer reset, tokens, vendor, base, components, utilities;\n\n@layer components {\n .content {\n --_gap: var(--popover-gap);\n\n position: fixed;\n z-index: var(--popover-layer);\n inset-block-start: var(--_y);\n inset-inline-start: var(--_x);\n display: flex;\n flex-direction: column;\n gap: var(--popover-gap);\n inline-size: var(--popover-width);\n max-inline-size: calc(100vw - 2 * var(--space-4));\n padding: var(--popover-padding);\n border: var(--size-hairline) solid var(--popover-border);\n border-radius: var(--popover-radius);\n background-color: var(--popover-bg);\n color: var(--popover-fg);\n font-family: var(--font-family-body);\n box-shadow: var(--popover-shadow);\n animation: fade var(--popover-duration) var(--motion-easing-standard);\n\n &:focus-visible {\n outline: var(--popover-focus-ring-width) solid var(--popover-focus-ring);\n outline-offset: var(--popover-focus-ring-offset);\n }\n }\n\n .title {\n margin: 0;\n font-family: var(--font-family-display);\n font-size: var(--font-size-md);\n font-weight: var(--font-weight-semibold);\n line-height: var(--font-line-height-tight);\n }\n\n @keyframes fade {\n from {\n opacity: 0;\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n .content {\n animation: none;\n }\n }\n}\n","import {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useId,\n useRef,\n useState,\n type ButtonHTMLAttributes,\n type HTMLAttributes,\n type ReactNode,\n type Ref,\n} from 'react';\nimport { createPortal } from 'react-dom';\nimport { renderAsChild } from '../internal/asChild';\nimport { classes } from '../internal/classes';\nimport { useFloatingPosition, type FloatingPlacement } from '../internal/floating';\nimport { useDismiss } from '../internal/useDismiss';\nimport styles from './Popover.module.css';\n\nexport type PopoverPlacement = FloatingPlacement;\n\ninterface PopoverContextValue {\n open: boolean;\n setOpen: (open: boolean) => void;\n contentId: string;\n titleId: string;\n placement: PopoverPlacement;\n floating: ReturnType<typeof useFloatingPosition>;\n}\n\nconst PopoverContext = createContext<PopoverContextValue | null>(null);\n\nfunction usePopover(part: string): PopoverContextValue {\n const context = useContext(PopoverContext);\n if (!context) throw new Error(`${part} must be rendered inside <Popover>`);\n return context;\n}\n\nexport interface PopoverProps {\n /** Controlled open state. */\n open?: boolean;\n /** @default false */\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n /** Preferred side; flips when there is no room. @default 'bottom-start' */\n placement?: PopoverPlacement;\n children: ReactNode;\n}\n\n/**\n * A non-modal layer anchored to its trigger: a small form, a filter, a\n * detail panel. The page stays interactive; Escape, a click outside or\n * `Popover.Close` dismiss it and focus returns to the trigger. Compose with\n * `Popover.Trigger`, `Popover.Content` and `Popover.Close`. For anything that\n * must block the page, use Dialog.\n *\n * @status stable\n * @category Overlays\n * @accessibility A non-modal `role=\"dialog\"` named by `title` (or `aria-label`); the trigger has `aria-haspopup=\"dialog\"` and `aria-expanded`. Focus moves to the first focusable element on open and back to the trigger on close; Escape and a click outside dismiss it.\n * @do Give it a `title` or `aria-label`.\n * Use `Popover.Close` inside forms so a keyboard user has a clear exit.\n * @dont Put a long form or a destructive confirmation in it; use Dialog.\n * Open it on hover; that is Tooltip.\n */\nexport function Popover({ open, defaultOpen = false, onOpenChange, placement = 'bottom-start', children }: PopoverProps) {\n const [uncontrolled, setUncontrolled] = useState(defaultOpen);\n const controlled = open !== undefined;\n const isOpen = controlled ? open : uncontrolled;\n const setOpen = useCallback(\n (next: boolean) => {\n if (!controlled) setUncontrolled(next);\n onOpenChange?.(next);\n },\n [controlled, onOpenChange],\n );\n const id = useId();\n const floating = useFloatingPosition({ open: isOpen, placement });\n\n return (\n <PopoverContext.Provider value={{ open: isOpen, setOpen, contentId: `${id}-content`, titleId: `${id}-title`, placement, floating }}>\n {children}\n </PopoverContext.Provider>\n );\n}\n\ninterface PopoverTriggerProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n /** Render the child element as the trigger instead of a plain button. @default false */\n asChild?: boolean;\n ref?: Ref<HTMLButtonElement>;\n children: ReactNode;\n}\n\nfunction PopoverTrigger({ asChild = false, onClick, ref, children, ...rest }: PopoverTriggerProps) {\n const popover = usePopover('Popover.Trigger');\n const props = {\n ...rest,\n ref: popover.floating.refs.setReference,\n 'aria-haspopup': 'dialog' as const,\n 'aria-expanded': popover.open,\n 'aria-controls': popover.open ? popover.contentId : undefined,\n onClick: (event: React.MouseEvent<HTMLButtonElement>) => {\n onClick?.(event);\n if (!event.defaultPrevented) popover.setOpen(!popover.open);\n },\n };\n if (asChild) {\n // eslint-disable-next-line react-hooks/refs -- forwarded to the reference element, not read\n return renderAsChild('Popover.Trigger', children, { ...props, ref: mergeRefs(ref, popover.floating.refs.setReference) });\n }\n return (\n <button type=\"button\" {...props} ref={mergeRefs(ref, popover.floating.refs.setReference)}>\n {children}\n </button>\n );\n}\n\nfunction mergeRefs<T>(a: Ref<T> | undefined, b: (node: T | null) => void) {\n return (node: T | null) => {\n b(node);\n if (typeof a === 'function') a(node);\n else if (a) a.current = node;\n };\n}\n\ninterface PopoverContentProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {\n /** Rendered as the dialog's heading and used as its accessible name. Otherwise pass `aria-label`. */\n title?: ReactNode;\n ref?: Ref<HTMLDivElement>;\n children: ReactNode;\n}\n\nfunction PopoverContent({ title, className, ref, children, ...rest }: PopoverContentProps) {\n const popover = usePopover('Popover.Content');\n const { refs, positionStyle, placement } = popover.floating;\n const contentRef = useRef<HTMLDivElement | null>(null);\n\n useDismiss({\n open: popover.open,\n onDismiss: () => popover.setOpen(false),\n inside: () => [refs.reference.current as Element | null, refs.floating.current],\n });\n\n // Move focus in on open; give it back to the trigger on close.\n useEffect(() => {\n if (popover.open) {\n const content = contentRef.current;\n if (!content) return;\n const first = content.querySelector<HTMLElement>('input, select, textarea, button, a[href], [tabindex]:not([tabindex=\"-1\"])');\n (first ?? content).focus();\n return () => {\n const reference = refs.reference.current as HTMLElement | null;\n if (content.contains(document.activeElement) || document.activeElement === document.body) reference?.focus();\n };\n }\n }, [popover.open, refs.reference]);\n\n if (!popover.open) return null;\n return createPortal(\n <div\n {...rest}\n ref={mergeRefs(ref, (node) => {\n contentRef.current = node;\n refs.setFloating(node);\n })}\n id={popover.contentId}\n role=\"dialog\"\n aria-labelledby={title ? popover.titleId : undefined}\n tabIndex={-1}\n className={classes(styles.content, className)}\n data-placement={placement}\n // eslint-disable-next-line react/forbid-dom-props -- per-instance position (--_x/--_y), see internal/floating.ts\n style={positionStyle}\n >\n {title && (\n <h2 id={popover.titleId} className={styles.title}>\n {title}\n </h2>\n )}\n {children}\n </div>,\n document.body,\n );\n}\n\ninterface PopoverCloseProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n asChild?: boolean;\n children: ReactNode;\n}\n\nfunction PopoverClose({ asChild = false, onClick, children, ...rest }: PopoverCloseProps) {\n const popover = usePopover('Popover.Close');\n const props = {\n ...rest,\n onClick: (event: React.MouseEvent<HTMLButtonElement>) => {\n onClick?.(event);\n if (!event.defaultPrevented) popover.setOpen(false);\n },\n };\n if (asChild) return renderAsChild('Popover.Close', children, props);\n return (\n <button type=\"button\" {...props}>\n {children}\n </button>\n );\n}\n\nPopover.displayName = 'Popover';\nPopoverTrigger.displayName = 'Popover.Trigger';\nPopoverContent.displayName = 'Popover.Content';\nPopoverClose.displayName = 'Popover.Close';\n\nPopover.Trigger = PopoverTrigger;\nPopover.Content = PopoverContent;\nPopover.Close = PopoverClose;\n"]}
@@ -1,4 +1,4 @@
1
- import { renderAsChild } from './chunk-ZVDN3GRI.js';
1
+ import { renderAsChild } from './chunk-QJG5ILK5.js';
2
2
  import { classes } from './chunk-MI4QUKQS.js';
3
3
  import { createContext, useContext, useId, useState, useCallback, useLayoutEffect } from 'react';
4
4
  import { jsx, jsxs } from 'react/jsx-runtime';
@@ -91,5 +91,5 @@ Field.Description = FieldDescription;
91
91
  Field.Error = FieldError;
92
92
 
93
93
  export { Field, useField };
94
- //# sourceMappingURL=chunk-M5VL22MY.js.map
95
- //# sourceMappingURL=chunk-M5VL22MY.js.map
94
+ //# sourceMappingURL=chunk-SXMORGSG.js.map
95
+ //# sourceMappingURL=chunk-SXMORGSG.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/field/Field.module.css","../src/field/Field.tsx"],"names":["field","label","required","description","error"],"mappings":";;;;;;AAAA,IAAA,aAAA,GAAA;AAAA,EAKG,KAAA,EAAAA,aAAAA;AAAA,EAMA,KAAA,EAAAC,aAAAA;AAAA,EAMA,QAAA,EAAAC,gBAAAA;AAAA,EAKA,WAAA,EAAAC,mBAAAA;AAAA,EAMA,KAAA,EAAAC;AAAA,CAAA;ACIH,IAAM,YAAA,GAAe,cAAwC,IAAI,CAAA;AAEjE,IAAM,MAAM,OAAO,OAAA,KAAY,WAAA,IAAe,OAAA,CAAQ,KAAK,QAAA,KAAa,YAAA;AAGjE,SAAS,QAAA,GAA8B;AAC5C,EAAA,MAAM,OAAA,GAAU,WAAW,YAAY,CAAA;AACvC,EAAA,IAAI,CAAC,OAAA,EAAS,MAAM,IAAI,MAAM,sCAAsC,CAAA;AACpE,EAAA,OAAO,OAAA;AACT;AAmCO,SAAS,KAAA,CAAM,EAAE,EAAA,EAAI,OAAA,GAAU,OAAO,QAAA,GAAW,KAAA,EAAO,QAAA,GAAW,KAAA,EAAO,SAAA,EAAW,GAAA,EAAK,QAAA,EAAU,GAAG,MAAK,EAAe;AAChI,EAAA,MAAM,SAAS,KAAA,EAAM;AACrB,EAAA,MAAM,YAAY,EAAA,IAAM,MAAA;AAGxB,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,QAAA,CAA+B,EAAE,WAAA,EAAa,CAAA,EAAG,KAAA,EAAO,CAAA,EAAG,CAAA;AAErF,EAAA,MAAM,QAAA,GAAW,WAAA,CAAY,CAAC,IAAA,KAAe;AAC3C,IAAA,QAAA,CAAS,CAAC,OAAA,KAAY;AACpB,MAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,IAAI,CAAA,GAAI,CAAA;AAC7B,MAAA,IAAI,GAAA,IAAO,IAAA,KAAS,CAAA,EAAG,OAAA,CAAQ,IAAA,CAAK,8BAA8B,IAAA,KAAS,OAAA,GAAU,OAAA,GAAU,aAAa,CAAA,+BAAA,CAAiC,CAAA;AAC7I,MAAA,OAAO,EAAE,GAAG,OAAA,EAAS,CAAC,IAAI,GAAG,IAAA,EAAK;AAAA,IACpC,CAAC,CAAA;AACD,IAAA,OAAO,MAAM,QAAA,CAAS,CAAC,aAAa,EAAE,GAAG,SAAS,CAAC,IAAI,GAAG,IAAA,CAAK,IAAI,CAAA,EAAG,OAAA,CAAQ,IAAI,CAAA,GAAI,CAAC,GAAE,CAAE,CAAA;AAAA,EAC7F,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,WAAA,GACJ,CAAC,KAAA,CAAM,WAAA,GAAc,KAAK,CAAA,EAAG,SAAS,gBAAgB,KAAA,CAAM,KAAA,GAAQ,KAAK,CAAA,EAAG,SAAS,QAAQ,CAAA,CAAE,MAAA,CAAO,OAAO,CAAA,CAAE,IAAA,CAAK,GAAG,CAAA,IACvH,MAAA;AAEF,EAAA,2BACG,YAAA,CAAa,QAAA,EAAb,EAAsB,KAAA,EAAO,EAAE,EAAA,EAAI,SAAA,EAAW,OAAA,EAAS,CAAA,EAAG,SAAS,CAAA,MAAA,CAAA,EAAU,OAAA,EAAS,UAAU,QAAA,EAAU,WAAA,EAAa,UAAS,EAC/H,QAAA,kBAAA,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACE,GAAG,IAAA;AAAA,MACJ,GAAA;AAAA,MACA,SAAA,EAAW,OAAA,CAAQ,aAAA,CAAO,KAAA,EAAO,SAAS,CAAA;AAAA,MAC1C,cAAA,EAAc,UAAU,EAAA,GAAK,MAAA;AAAA,MAC7B,eAAA,EAAe,WAAW,EAAA,GAAK,MAAA;AAAA,MAC/B,eAAA,EAAe,WAAW,EAAA,GAAK,MAAA;AAAA,MAE9B;AAAA;AAAA,GACH,EACF,CAAA;AAEJ;AAcA,SAAS,UAAA,CAAW,EAAE,EAAA,GAAK,OAAA,EAAS,WAAW,GAAA,EAAK,QAAA,EAAU,GAAG,IAAA,EAAK,EAAoB;AACxF,EAAA,MAAM,QAAQ,QAAA,EAAS;AACvB,EAAA,MAAM,MAAA,GAAS,KAAA,CAAM,QAAA,oBACnB,GAAA,CAAC,MAAA,EAAA,EAAK,WAAW,aAAA,CAAO,QAAA,EAAU,aAAA,EAAY,MAAA,EAAO,QAAA,EAAA,GAAA,EAErD,CAAA;AAEF,EAAA,IAAI,OAAO,MAAA,EAAQ;AACjB,IAAA,uBACE,IAAA,CAAC,MAAA,EAAA,EAAM,GAAG,IAAA,EAAM,EAAA,EAAI,KAAA,CAAM,OAAA,EAAS,SAAA,EAAW,OAAA,CAAQ,aAAA,CAAO,KAAA,EAAO,SAAS,CAAA,EAC1E,QAAA,EAAA;AAAA,MAAA,QAAA;AAAA,MACA;AAAA,KAAA,EACH,CAAA;AAAA,EAEJ;AACA,EAAA,uBACE,IAAA,CAAC,OAAA,EAAA,EAAO,GAAG,IAAA,EAAM,GAAA,EAAU,OAAA,EAAS,KAAA,CAAM,EAAA,EAAI,SAAA,EAAW,OAAA,CAAQ,aAAA,CAAO,KAAA,EAAO,SAAS,CAAA,EACrF,QAAA,EAAA;AAAA,IAAA,QAAA;AAAA,IACA;AAAA,GAAA,EACH,CAAA;AAEJ;AASA,SAAS,YAAA,CAAa,EAAE,kBAAA,EAAoB,KAAA,EAAO,UAAS,EAAsB;AAChF,EAAA,MAAM,QAAQ,QAAA,EAAS;AACvB,EAAA,OAAO,aAAA,CAAc,iBAAiB,QAAA,EAAU;AAAA,IAC9C,IAAI,KAAA,CAAM,EAAA;AAAA,IACV,kBAAA,EAAoB,CAAC,KAAA,EAAO,KAAA,CAAM,WAAW,CAAA,CAAE,MAAA,CAAO,OAAO,CAAA,CAAE,IAAA,CAAK,GAAG,CAAA,IAAK,MAAA;AAAA,IAC5E,cAAA,EAAgB,MAAM,OAAA,IAAW,MAAA;AAAA,IACjC,QAAA,EAAU,MAAM,QAAA,IAAY,MAAA;AAAA,IAC5B,QAAA,EAAU,MAAM,QAAA,IAAY;AAAA,GAC7B,CAAA;AACH;AAOA,SAAS,iBAAiB,EAAE,SAAA,EAAW,KAAK,QAAA,EAAU,GAAG,MAAK,EAAmB;AAC/E,EAAA,MAAM,QAAQ,QAAA,EAAS;AACvB,EAAA,MAAM,EAAE,UAAS,GAAI,KAAA;AACrB,EAAA,eAAA,CAAgB,MAAM,QAAA,CAAS,aAAa,CAAA,EAAG,CAAC,QAAQ,CAAC,CAAA;AACzD,EAAA,2BACG,GAAA,EAAA,EAAG,GAAG,IAAA,EAAM,GAAA,EAAU,IAAI,CAAA,EAAG,KAAA,CAAM,EAAE,CAAA,YAAA,CAAA,EAAgB,WAAW,OAAA,CAAQ,aAAA,CAAO,WAAA,EAAa,SAAS,GACnG,QAAA,EACH,CAAA;AAEJ;AAEA,SAAS,WAAW,EAAE,SAAA,EAAW,KAAK,QAAA,EAAU,GAAG,MAAK,EAAmB;AACzE,EAAA,MAAM,QAAQ,QAAA,EAAS;AACvB,EAAA,MAAM,EAAE,UAAS,GAAI,KAAA;AACrB,EAAA,eAAA,CAAgB,MAAM,QAAA,CAAS,OAAO,CAAA,EAAG,CAAC,QAAQ,CAAC,CAAA;AACnD,EAAA,2BACG,GAAA,EAAA,EAAG,GAAG,MAAM,GAAA,EAAU,EAAA,EAAI,GAAG,KAAA,CAAM,EAAE,CAAA,MAAA,CAAA,EAAU,IAAA,EAAK,SAAQ,SAAA,EAAW,OAAA,CAAQ,cAAO,KAAA,EAAO,SAAS,GACpG,QAAA,EACH,CAAA;AAEJ;AAEA,KAAA,CAAM,WAAA,GAAc,OAAA;AACpB,UAAA,CAAW,WAAA,GAAc,aAAA;AACzB,YAAA,CAAa,WAAA,GAAc,eAAA;AAC3B,gBAAA,CAAiB,WAAA,GAAc,mBAAA;AAC/B,UAAA,CAAW,WAAA,GAAc,aAAA;AAEzB,KAAA,CAAM,KAAA,GAAQ,UAAA;AACd,KAAA,CAAM,OAAA,GAAU,YAAA;AAChB,KAAA,CAAM,WAAA,GAAc,gBAAA;AACpB,KAAA,CAAM,KAAA,GAAQ,UAAA","file":"chunk-M5VL22MY.js","sourcesContent":["/* Every value is a token (--field-*). The control itself brings its own styles. */\n\n@layer reset, tokens, vendor, base, components, utilities;\n\n@layer components {\n .field {\n display: flex;\n flex-direction: column;\n gap: var(--field-gap);\n }\n\n .label {\n font-size: var(--field-label-font-size);\n font-weight: var(--field-label-font-weight);\n color: var(--field-label-fg);\n }\n\n .required {\n margin-inline-start: var(--field-required-gap);\n color: var(--field-required-fg);\n }\n\n .description {\n margin: 0;\n font-size: var(--field-description-font-size);\n color: var(--field-description-fg);\n }\n\n .error {\n margin: 0;\n font-size: var(--field-error-font-size);\n color: var(--field-error-fg);\n }\n}\n","import {\n createContext,\n useCallback,\n useContext,\n useId,\n useLayoutEffect,\n useState,\n type HTMLAttributes,\n type LabelHTMLAttributes,\n type ReactNode,\n type Ref,\n} from 'react';\nimport { renderAsChild } from '../internal/asChild';\nimport { classes } from '../internal/classes';\nimport styles from './Field.module.css';\n\ntype Part = 'description' | 'error';\n\nexport interface FieldContextValue {\n /** The control's id; the label points at it. */\n id: string;\n /** The label's id, for controls that are labelled by reference (`aria-labelledby`), such as a radio group. */\n labelId: string;\n invalid: boolean;\n disabled: boolean;\n required: boolean;\n /** ids of the description and error that are actually mounted, space separated. */\n describedBy: string | undefined;\n /** Registers a mounted part; returns the unregister function. */\n register: (part: Part) => () => void;\n}\n\nconst FieldContext = createContext<FieldContextValue | null>(null);\n\nconst DEV = typeof process !== 'undefined' && process.env?.NODE_ENV !== 'production';\n\n/** The field's ids and state, for controls that wire themselves instead of using `Field.Control`. */\nexport function useField(): FieldContextValue {\n const context = useContext(FieldContext);\n if (!context) throw new Error('useField must be used inside <Field>');\n return context;\n}\n\nexport interface FieldProps extends HTMLAttributes<HTMLDivElement> {\n /** The control's id. Generated when omitted. */\n id?: string;\n /** @default false */\n invalid?: boolean;\n /** @default false */\n disabled?: boolean;\n /** @default false */\n required?: boolean;\n ref?: Ref<HTMLDivElement>;\n children: ReactNode;\n}\n\n/**\n * The wiring every form control shares: a label pointing at the control, a\n * description and an error exposed through `aria-describedby`, and invalid,\n * disabled and required state in one place. Only parts that are mounted end\n * up in `aria-describedby`, so no id ever dangles. Compose with\n * `Field.Label`, `Field.Control`, `Field.Description` and `Field.Error`\n * (one of each); state on the DOM as `data-invalid`, `data-disabled`,\n * `data-required`.\n *\n * Known limitation: parts register in a layout effect, so server-rendered\n * HTML carries no `aria-describedby` until hydration. The relationship is\n * complete for every interactive use; static HTML consumers should not rely\n * on it yet.\n *\n * @status stable\n * @category Forms\n * @accessibility Wires `label[for]`, `aria-describedby` (only mounted parts), `aria-invalid`, `aria-required` and `disabled` onto the control. Server-rendered HTML has no `aria-describedby` until hydration (a test pins the gap).\n * @do Use `Field.Label as=\"span\"` with `useField().labelId` for groups that cannot be labelled by `for`.\n * @dont Mount two `Field.Description` or two `Field.Error`; ids would collide (development warns).\n */\nexport function Field({ id, invalid = false, disabled = false, required = false, className, ref, children, ...rest }: FieldProps) {\n const autoId = useId();\n const controlId = id ?? autoId;\n // Counts, not booleans: a second instance of a part is a bug (duplicate ids)\n // and is reported in development instead of silently colliding.\n const [parts, setParts] = useState<Record<Part, number>>({ description: 0, error: 0 });\n\n const register = useCallback((part: Part) => {\n setParts((current) => {\n const next = current[part] + 1;\n if (DEV && next === 2) console.warn(`Field: more than one Field.${part === 'error' ? 'Error' : 'Description'} is mounted; their ids collide.`);\n return { ...current, [part]: next };\n });\n return () => setParts((current) => ({ ...current, [part]: Math.max(0, current[part] - 1) }));\n }, []);\n\n const describedBy =\n [parts.description > 0 && `${controlId}-description`, parts.error > 0 && `${controlId}-error`].filter(Boolean).join(' ') ||\n undefined;\n\n return (\n <FieldContext.Provider value={{ id: controlId, labelId: `${controlId}-label`, invalid, disabled, required, describedBy, register }}>\n <div\n {...rest}\n ref={ref}\n className={classes(styles.field, className)}\n data-invalid={invalid ? '' : undefined}\n data-disabled={disabled ? '' : undefined}\n data-required={required ? '' : undefined}\n >\n {children}\n </div>\n </FieldContext.Provider>\n );\n}\n\ninterface FieldLabelProps extends LabelHTMLAttributes<HTMLLabelElement> {\n /**\n * `label` points at the control with `for`. `span` is for controls that are\n * not labelable (a radio group, a fieldset): it carries `labelId` and the\n * control references it with `aria-labelledby`.\n * @default 'label'\n */\n as?: 'label' | 'span';\n ref?: Ref<HTMLLabelElement>;\n children: ReactNode;\n}\n\nfunction FieldLabel({ as = 'label', className, ref, children, ...rest }: FieldLabelProps) {\n const field = useField();\n const marker = field.required && (\n <span className={styles.required} aria-hidden=\"true\">\n *\n </span>\n );\n if (as === 'span') {\n return (\n <span {...rest} id={field.labelId} className={classes(styles.label, className)}>\n {children}\n {marker}\n </span>\n );\n }\n return (\n <label {...rest} ref={ref} htmlFor={field.id} className={classes(styles.label, className)}>\n {children}\n {marker}\n </label>\n );\n}\n\ninterface FieldControlProps {\n /** Extra ids to describe the control by, kept alongside the field's own. */\n 'aria-describedby'?: string;\n /** The single control element; the field's wiring is merged into it. */\n children: ReactNode;\n}\n\nfunction FieldControl({ 'aria-describedby': extra, children }: FieldControlProps) {\n const field = useField();\n return renderAsChild('Field.Control', children, {\n id: field.id,\n 'aria-describedby': [extra, field.describedBy].filter(Boolean).join(' ') || undefined,\n 'aria-invalid': field.invalid || undefined,\n disabled: field.disabled || undefined,\n required: field.required || undefined,\n });\n}\n\ninterface FieldTextProps extends HTMLAttributes<HTMLParagraphElement> {\n ref?: Ref<HTMLParagraphElement>;\n children?: ReactNode;\n}\n\nfunction FieldDescription({ className, ref, children, ...rest }: FieldTextProps) {\n const field = useField();\n const { register } = field;\n useLayoutEffect(() => register('description'), [register]);\n return (\n <p {...rest} ref={ref} id={`${field.id}-description`} className={classes(styles.description, className)}>\n {children}\n </p>\n );\n}\n\nfunction FieldError({ className, ref, children, ...rest }: FieldTextProps) {\n const field = useField();\n const { register } = field;\n useLayoutEffect(() => register('error'), [register]);\n return (\n <p {...rest} ref={ref} id={`${field.id}-error`} role=\"alert\" className={classes(styles.error, className)}>\n {children}\n </p>\n );\n}\n\nField.displayName = 'Field';\nFieldLabel.displayName = 'Field.Label';\nFieldControl.displayName = 'Field.Control';\nFieldDescription.displayName = 'Field.Description';\nFieldError.displayName = 'Field.Error';\n\nField.Label = FieldLabel;\nField.Control = FieldControl;\nField.Description = FieldDescription;\nField.Error = FieldError;\n"]}
1
+ {"version":3,"sources":["../src/field/Field.module.css","../src/field/Field.tsx"],"names":["field","label","required","description","error"],"mappings":"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","file":"chunk-SXMORGSG.js","sourcesContent":["/* Every value is a token (--field-*). The control itself brings its own styles. */\n\n@layer reset, tokens, vendor, base, components, utilities;\n\n@layer components {\n .field {\n display: flex;\n flex-direction: column;\n gap: var(--field-gap);\n }\n\n .label {\n font-size: var(--field-label-font-size);\n font-weight: var(--field-label-font-weight);\n color: var(--field-label-fg);\n }\n\n .required {\n margin-inline-start: var(--field-required-gap);\n color: var(--field-required-fg);\n }\n\n .description {\n margin: 0;\n font-size: var(--field-description-font-size);\n color: var(--field-description-fg);\n }\n\n .error {\n margin: 0;\n font-size: var(--field-error-font-size);\n color: var(--field-error-fg);\n }\n}\n","import {\n createContext,\n useCallback,\n useContext,\n useId,\n useLayoutEffect,\n useState,\n type HTMLAttributes,\n type LabelHTMLAttributes,\n type ReactNode,\n type Ref,\n} from 'react';\nimport { renderAsChild } from '../internal/asChild';\nimport { classes } from '../internal/classes';\nimport styles from './Field.module.css';\n\ntype Part = 'description' | 'error';\n\nexport interface FieldContextValue {\n /** The control's id; the label points at it. */\n id: string;\n /** The label's id, for controls that are labelled by reference (`aria-labelledby`), such as a radio group. */\n labelId: string;\n invalid: boolean;\n disabled: boolean;\n required: boolean;\n /** ids of the description and error that are actually mounted, space separated. */\n describedBy: string | undefined;\n /** Registers a mounted part; returns the unregister function. */\n register: (part: Part) => () => void;\n}\n\nconst FieldContext = createContext<FieldContextValue | null>(null);\n\nconst DEV = typeof process !== 'undefined' && process.env?.NODE_ENV !== 'production';\n\n/** The field's ids and state, for controls that wire themselves instead of using `Field.Control`. */\nexport function useField(): FieldContextValue {\n const context = useContext(FieldContext);\n if (!context) throw new Error('useField must be used inside <Field>');\n return context;\n}\n\nexport interface FieldProps extends HTMLAttributes<HTMLDivElement> {\n /** The control's id. Generated when omitted. */\n id?: string;\n /** @default false */\n invalid?: boolean;\n /** @default false */\n disabled?: boolean;\n /** @default false */\n required?: boolean;\n ref?: Ref<HTMLDivElement>;\n children: ReactNode;\n}\n\n/**\n * The wiring every form control shares: a label pointing at the control, a\n * description and an error exposed through `aria-describedby`, and invalid,\n * disabled and required state in one place. Only parts that are mounted end\n * up in `aria-describedby`, so no id ever dangles. Compose with\n * `Field.Label`, `Field.Control`, `Field.Description` and `Field.Error`\n * (one of each); state on the DOM as `data-invalid`, `data-disabled`,\n * `data-required`.\n *\n * Known limitation: parts register in a layout effect, so server-rendered\n * HTML carries no `aria-describedby` until hydration. The relationship is\n * complete for every interactive use; static HTML consumers should not rely\n * on it yet.\n *\n * @status stable\n * @category Forms\n * @accessibility Wires `label[for]`, `aria-describedby` (only mounted parts), `aria-invalid`, `aria-required` and `disabled` onto the control. Server-rendered HTML has no `aria-describedby` until hydration (a test pins the gap).\n * @do Use `Field.Label as=\"span\"` with `useField().labelId` for groups that cannot be labelled by `for`.\n * @dont Mount two `Field.Description` or two `Field.Error`; ids would collide (development warns).\n */\nexport function Field({ id, invalid = false, disabled = false, required = false, className, ref, children, ...rest }: FieldProps) {\n const autoId = useId();\n const controlId = id ?? autoId;\n // Counts, not booleans: a second instance of a part is a bug (duplicate ids)\n // and is reported in development instead of silently colliding.\n const [parts, setParts] = useState<Record<Part, number>>({ description: 0, error: 0 });\n\n const register = useCallback((part: Part) => {\n setParts((current) => {\n const next = current[part] + 1;\n if (DEV && next === 2) console.warn(`Field: more than one Field.${part === 'error' ? 'Error' : 'Description'} is mounted; their ids collide.`);\n return { ...current, [part]: next };\n });\n return () => setParts((current) => ({ ...current, [part]: Math.max(0, current[part] - 1) }));\n }, []);\n\n const describedBy =\n [parts.description > 0 && `${controlId}-description`, parts.error > 0 && `${controlId}-error`].filter(Boolean).join(' ') ||\n undefined;\n\n return (\n <FieldContext.Provider value={{ id: controlId, labelId: `${controlId}-label`, invalid, disabled, required, describedBy, register }}>\n <div\n {...rest}\n ref={ref}\n className={classes(styles.field, className)}\n data-invalid={invalid ? '' : undefined}\n data-disabled={disabled ? '' : undefined}\n data-required={required ? '' : undefined}\n >\n {children}\n </div>\n </FieldContext.Provider>\n );\n}\n\ninterface FieldLabelProps extends LabelHTMLAttributes<HTMLLabelElement> {\n /**\n * `label` points at the control with `for`. `span` is for controls that are\n * not labelable (a radio group, a fieldset): it carries `labelId` and the\n * control references it with `aria-labelledby`.\n * @default 'label'\n */\n as?: 'label' | 'span';\n ref?: Ref<HTMLLabelElement>;\n children: ReactNode;\n}\n\nfunction FieldLabel({ as = 'label', className, ref, children, ...rest }: FieldLabelProps) {\n const field = useField();\n const marker = field.required && (\n <span className={styles.required} aria-hidden=\"true\">\n *\n </span>\n );\n if (as === 'span') {\n return (\n <span {...rest} id={field.labelId} className={classes(styles.label, className)}>\n {children}\n {marker}\n </span>\n );\n }\n return (\n <label {...rest} ref={ref} htmlFor={field.id} className={classes(styles.label, className)}>\n {children}\n {marker}\n </label>\n );\n}\n\ninterface FieldControlProps {\n /** Extra ids to describe the control by, kept alongside the field's own. */\n 'aria-describedby'?: string;\n /** The single control element; the field's wiring is merged into it. */\n children: ReactNode;\n}\n\nfunction FieldControl({ 'aria-describedby': extra, children }: FieldControlProps) {\n const field = useField();\n return renderAsChild('Field.Control', children, {\n id: field.id,\n 'aria-describedby': [extra, field.describedBy].filter(Boolean).join(' ') || undefined,\n 'aria-invalid': field.invalid || undefined,\n disabled: field.disabled || undefined,\n required: field.required || undefined,\n });\n}\n\ninterface FieldTextProps extends HTMLAttributes<HTMLParagraphElement> {\n ref?: Ref<HTMLParagraphElement>;\n children?: ReactNode;\n}\n\nfunction FieldDescription({ className, ref, children, ...rest }: FieldTextProps) {\n const field = useField();\n const { register } = field;\n useLayoutEffect(() => register('description'), [register]);\n return (\n <p {...rest} ref={ref} id={`${field.id}-description`} className={classes(styles.description, className)}>\n {children}\n </p>\n );\n}\n\nfunction FieldError({ className, ref, children, ...rest }: FieldTextProps) {\n const field = useField();\n const { register } = field;\n useLayoutEffect(() => register('error'), [register]);\n return (\n <p {...rest} ref={ref} id={`${field.id}-error`} role=\"alert\" className={classes(styles.error, className)}>\n {children}\n </p>\n );\n}\n\nField.displayName = 'Field';\nFieldLabel.displayName = 'Field.Label';\nFieldControl.displayName = 'Field.Control';\nFieldDescription.displayName = 'Field.Description';\nFieldError.displayName = 'Field.Error';\n\nField.Label = FieldLabel;\nField.Control = FieldControl;\nField.Description = FieldDescription;\nField.Error = FieldError;\n"]}
@@ -1,4 +1,4 @@
1
- import { ToggleField } from './chunk-6BIEW4WJ.js';
1
+ import { ToggleField } from './chunk-Q6SYKNZ5.js';
2
2
  import { useCallback } from 'react';
3
3
  import { jsx } from 'react/jsx-runtime';
4
4
 
@@ -61,5 +61,5 @@ function Checkbox({
61
61
  Checkbox.displayName = "Checkbox";
62
62
 
63
63
  export { Checkbox };
64
- //# sourceMappingURL=chunk-Z6SS4G4V.js.map
65
- //# sourceMappingURL=chunk-Z6SS4G4V.js.map
64
+ //# sourceMappingURL=chunk-UMK4D234.js.map
65
+ //# sourceMappingURL=chunk-UMK4D234.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/checkbox/Checkbox.module.css","../src/checkbox/Checkbox.tsx"],"names":["checkbox","row","input"],"mappings":";;;;;AAAA,IAAA,gBAAA,GAAA;AAAA,EASG,QAAA,EAAAA,mBAAAA;AAAA,EAWA,GAAA,EAAAC,cAAAA;AAAA,EAMA,KAAA,EAAAC;AAAA,CAAA;ACWI,SAAS,QAAA,CAAS;AAAA,EACvB,KAAA;AAAA,EACA,WAAA;AAAA,EACA,KAAA;AAAA,EACA,IAAA,GAAO,IAAA;AAAA,EACP,aAAA,GAAgB,KAAA;AAAA,EAChB,QAAA;AAAA,EACA,QAAA;AAAA,EACA,EAAA;AAAA,EACA,SAAA;AAAA,EACA,GAAA;AAAA,EACA,kBAAA,EAAoB,WAAA;AAAA,EACpB,GAAG;AACL,CAAA,EAAkB;AAEhB,EAAA,MAAM,MAAA,GAAS,WAAA;AAAA,IACb,CAAC,OAAA,KAAqC;AACpC,MAAA,IAAI,OAAA,UAAiB,aAAA,GAAgB,aAAA;AACrC,MAAA,IAAI,OAAO,GAAA,KAAQ,UAAA,EAAY,GAAA,CAAI,OAAO,CAAA;AAAA,WAAA,IACjC,GAAA,MAAS,OAAA,GAAU,OAAA;AAAA,IAC9B,CAAA;AAAA,IACA,CAAC,eAAe,GAAG;AAAA,GACrB;AAEA,EAAA,uBACE,GAAA;AAAA,IAAC,WAAA;AAAA,IAAA;AAAA,MACC,KAAA;AAAA,MACA,WAAA;AAAA,MACA,KAAA;AAAA,MACA,IAAA;AAAA,MACA,QAAA;AAAA,MACA,QAAA;AAAA,MACA,EAAA;AAAA,MACA,SAAA;AAAA,MACA,eAAe,gBAAA,CAAO,QAAA;AAAA,MACtB,cAAc,gBAAA,CAAO,GAAA;AAAA,MACrB,kBAAA,EAAkB,WAAA;AAAA,MAClB,OAAA,kBACE,GAAA;AAAA,QAAC,OAAA;AAAA,QAAA;AAAA,UACE,GAAG,IAAA;AAAA,UACJ,GAAA,EAAK,MAAA;AAAA,UACL,IAAA,EAAK,UAAA;AAAA,UACL,WAAW,gBAAA,CAAO,KAAA;AAAA,UAClB,cAAA,EAAc,gBAAgB,OAAA,GAAU,MAAA;AAAA,UACxC,oBAAA,EAAoB,gBAAgB,EAAA,GAAK;AAAA;AAAA;AAC3C;AAAA,GAEJ;AAEJ;AAEA,QAAA,CAAS,WAAA,GAAc,UAAA","file":"chunk-Z6SS4G4V.js","sourcesContent":["/*\n * Every value is a token (--checkbox-*). Size and invalid state are resolved\n * into private custom properties on the root, so the input has one rule per\n * property and no selector ordering to maintain.\n */\n\n@layer reset, tokens, vendor, base, components, utilities;\n\n@layer components {\n .checkbox {\n --_size: var(--checkbox-size-md);\n --_border: var(--checkbox-border);\n\n font-family: var(--font-family-body);\n\n &[data-size=\"sm\"] { --_size: var(--checkbox-size-sm); }\n &[data-size=\"lg\"] { --_size: var(--checkbox-size-lg); }\n &[data-invalid] { --_border: var(--checkbox-border-invalid); }\n }\n\n .row {\n display: flex;\n align-items: center;\n gap: var(--checkbox-gap);\n }\n\n .input {\n display: grid;\n flex: none;\n place-content: center;\n inline-size: var(--_size);\n block-size: var(--_size);\n margin: 0;\n border: var(--size-hairline) solid var(--_border);\n border-radius: var(--checkbox-radius);\n background-color: var(--checkbox-bg);\n appearance: none;\n cursor: pointer;\n transition:\n background-color var(--checkbox-motion-duration) var(--motion-easing-standard),\n border-color var(--checkbox-motion-duration) var(--motion-easing-standard);\n\n /* Sized from the box, not in percent: a grid item's percentage resolves against an auto area and collapses. */\n &::after {\n content: \"\";\n inline-size: calc(var(--_size) * 0.3);\n block-size: calc(var(--_size) * 0.55);\n border-style: solid;\n border-color: var(--checkbox-check);\n border-width: 0 var(--checkbox-check-width) var(--checkbox-check-width) 0;\n rotate: 45deg;\n translate: 0 -10%;\n opacity: 0;\n }\n\n &:checked,\n &:indeterminate {\n border-color: var(--checkbox-bg-checked);\n background-color: var(--checkbox-bg-checked);\n\n &::after {\n opacity: 1;\n }\n }\n\n &:indeterminate::after {\n inline-size: calc(var(--_size) * 0.55);\n block-size: 0;\n border-width: 0 0 var(--checkbox-check-width);\n rotate: 0deg;\n translate: 0 0;\n }\n\n &:focus-visible {\n outline: var(--checkbox-focus-ring-width) solid var(--checkbox-focus-ring);\n outline-offset: var(--checkbox-focus-ring-offset);\n }\n\n &:disabled {\n cursor: not-allowed;\n opacity: 0.55;\n }\n\n &:hover:not(:disabled, :checked, :indeterminate) {\n border-color: var(--checkbox-border-hover);\n }\n\n &:hover:not(:disabled):is(:checked, :indeterminate) {\n border-color: var(--checkbox-bg-checked-hover);\n background-color: var(--checkbox-bg-checked-hover);\n }\n }\n}\n","import { useCallback, type InputHTMLAttributes, type ReactNode, type Ref } from 'react';\nimport { ToggleField, type ToggleSize } from '../internal/ToggleField';\nimport styles from './Checkbox.module.css';\n\nexport type CheckboxSize = ToggleSize;\n\nexport interface CheckboxProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'size' | 'type'> {\n /** Visible label beside the box. */\n label: ReactNode;\n description?: ReactNode;\n /** Presence marks the control invalid and announces the message. */\n error?: ReactNode;\n /** @default 'md' */\n size?: CheckboxSize;\n /** The \"some selected\" state; visual and `aria-checked=\"mixed\"`, independent of `checked`. @default false */\n indeterminate?: boolean;\n /** The `<input>` element. */\n ref?: Ref<HTMLInputElement>;\n /** Applied to the wrapper, not the input. */\n className?: string;\n}\n\n/**\n * A native checkbox drawn with tokens: `appearance: none` on the input, the\n * box and tick in CSS, so keyboard, forms and assistive technology are the\n * browser's own. Label, description and error come from Field. Controlled and\n * uncontrolled behave like the native input. State is the native `:checked`\n * and `:indeterminate`, plus `data-indeterminate` on the input.\n *\n * @status stable\n * @category Forms\n * @accessibility A native `input type=\"checkbox\"` with `appearance: none`; label, description and error wire through Field. `indeterminate` sets the DOM property and `aria-checked=\"mixed\"`. Keyboard: Space toggles.\n * @do Use `indeterminate` for a parent whose children are partly selected.\n * Group related checkboxes under a `fieldset`.\n * @dont Use it for an immediate setting; use Switch.\n * Hide the label; the description does not name the control.\n */\nexport function Checkbox({\n label,\n description,\n error,\n size = 'md',\n indeterminate = false,\n required,\n disabled,\n id,\n className,\n ref,\n 'aria-describedby': describedBy,\n ...rest\n}: CheckboxProps) {\n // `indeterminate` is a property, not an attribute: set it on the element as it mounts and whenever it changes.\n const setRef = useCallback(\n (element: HTMLInputElement | null) => {\n if (element) element.indeterminate = indeterminate;\n if (typeof ref === 'function') ref(element);\n else if (ref) ref.current = element;\n },\n [indeterminate, ref],\n );\n\n return (\n <ToggleField\n label={label}\n description={description}\n error={error}\n size={size}\n required={required}\n disabled={disabled}\n id={id}\n className={className}\n rootClassName={styles.checkbox}\n rowClassName={styles.row}\n aria-describedby={describedBy}\n control={\n <input\n {...rest}\n ref={setRef}\n type=\"checkbox\"\n className={styles.input}\n aria-checked={indeterminate ? 'mixed' : undefined}\n data-indeterminate={indeterminate ? '' : undefined}\n />\n }\n />\n );\n}\n\nCheckbox.displayName = 'Checkbox';\n"]}
1
+ {"version":3,"sources":["../src/checkbox/Checkbox.module.css","../src/checkbox/Checkbox.tsx"],"names":["checkbox","row","input"],"mappings":";;;;;AAAA,IAAA,gBAAA,GAAA;AAAA,EASG,QAAA,EAAAA,mBAAAA;AAAA,EAWA,GAAA,EAAAC,cAAAA;AAAA,EAMA,KAAA,EAAAC;AAAA,CAAA;ACWI,SAAS,QAAA,CAAS;AAAA,EACvB,KAAA;AAAA,EACA,WAAA;AAAA,EACA,KAAA;AAAA,EACA,IAAA,GAAO,IAAA;AAAA,EACP,aAAA,GAAgB,KAAA;AAAA,EAChB,QAAA;AAAA,EACA,QAAA;AAAA,EACA,EAAA;AAAA,EACA,SAAA;AAAA,EACA,GAAA;AAAA,EACA,kBAAA,EAAoB,WAAA;AAAA,EACpB,GAAG;AACL,CAAA,EAAkB;AAEhB,EAAA,MAAM,MAAA,GAAS,WAAA;AAAA,IACb,CAAC,OAAA,KAAqC;AACpC,MAAA,IAAI,OAAA,UAAiB,aAAA,GAAgB,aAAA;AACrC,MAAA,IAAI,OAAO,GAAA,KAAQ,UAAA,EAAY,GAAA,CAAI,OAAO,CAAA;AAAA,WAAA,IACjC,GAAA,MAAS,OAAA,GAAU,OAAA;AAAA,IAC9B,CAAA;AAAA,IACA,CAAC,eAAe,GAAG;AAAA,GACrB;AAEA,EAAA,uBACE,GAAA;AAAA,IAAC,WAAA;AAAA,IAAA;AAAA,MACC,KAAA;AAAA,MACA,WAAA;AAAA,MACA,KAAA;AAAA,MACA,IAAA;AAAA,MACA,QAAA;AAAA,MACA,QAAA;AAAA,MACA,EAAA;AAAA,MACA,SAAA;AAAA,MACA,eAAe,gBAAA,CAAO,QAAA;AAAA,MACtB,cAAc,gBAAA,CAAO,GAAA;AAAA,MACrB,kBAAA,EAAkB,WAAA;AAAA,MAClB,OAAA,kBACE,GAAA;AAAA,QAAC,OAAA;AAAA,QAAA;AAAA,UACE,GAAG,IAAA;AAAA,UACJ,GAAA,EAAK,MAAA;AAAA,UACL,IAAA,EAAK,UAAA;AAAA,UACL,WAAW,gBAAA,CAAO,KAAA;AAAA,UAClB,cAAA,EAAc,gBAAgB,OAAA,GAAU,MAAA;AAAA,UACxC,oBAAA,EAAoB,gBAAgB,EAAA,GAAK;AAAA;AAAA;AAC3C;AAAA,GAEJ;AAEJ;AAEA,QAAA,CAAS,WAAA,GAAc,UAAA","file":"chunk-UMK4D234.js","sourcesContent":["/*\n * Every value is a token (--checkbox-*). Size and invalid state are resolved\n * into private custom properties on the root, so the input has one rule per\n * property and no selector ordering to maintain.\n */\n\n@layer reset, tokens, vendor, base, components, utilities;\n\n@layer components {\n .checkbox {\n --_size: var(--checkbox-size-md);\n --_border: var(--checkbox-border);\n\n font-family: var(--font-family-body);\n\n &[data-size=\"sm\"] { --_size: var(--checkbox-size-sm); }\n &[data-size=\"lg\"] { --_size: var(--checkbox-size-lg); }\n &[data-invalid] { --_border: var(--checkbox-border-invalid); }\n }\n\n .row {\n display: flex;\n align-items: center;\n gap: var(--checkbox-gap);\n }\n\n .input {\n display: grid;\n flex: none;\n place-content: center;\n inline-size: var(--_size);\n block-size: var(--_size);\n margin: 0;\n border: var(--size-hairline) solid var(--_border);\n border-radius: var(--checkbox-radius);\n background-color: var(--checkbox-bg);\n appearance: none;\n cursor: pointer;\n transition:\n background-color var(--checkbox-motion-duration) var(--motion-easing-standard),\n border-color var(--checkbox-motion-duration) var(--motion-easing-standard);\n\n /* Sized from the box, not in percent: a grid item's percentage resolves against an auto area and collapses. */\n &::after {\n content: \"\";\n inline-size: calc(var(--_size) * 0.3);\n block-size: calc(var(--_size) * 0.55);\n border-style: solid;\n border-color: var(--checkbox-check);\n border-width: 0 var(--checkbox-check-width) var(--checkbox-check-width) 0;\n rotate: 45deg;\n translate: 0 -10%;\n opacity: 0;\n }\n\n &:checked,\n &:indeterminate {\n border-color: var(--checkbox-bg-checked);\n background-color: var(--checkbox-bg-checked);\n\n &::after {\n opacity: 1;\n }\n }\n\n &:indeterminate::after {\n inline-size: calc(var(--_size) * 0.55);\n block-size: 0;\n border-width: 0 0 var(--checkbox-check-width);\n rotate: 0deg;\n translate: 0 0;\n }\n\n &:focus-visible {\n outline: var(--checkbox-focus-ring-width) solid var(--checkbox-focus-ring);\n outline-offset: var(--checkbox-focus-ring-offset);\n }\n\n &:disabled {\n cursor: not-allowed;\n opacity: 0.55;\n }\n\n &:hover:not(:disabled, :checked, :indeterminate) {\n border-color: var(--checkbox-border-hover);\n }\n\n &:hover:not(:disabled):is(:checked, :indeterminate) {\n border-color: var(--checkbox-bg-checked-hover);\n background-color: var(--checkbox-bg-checked-hover);\n }\n }\n}\n","import { useCallback, type InputHTMLAttributes, type ReactNode, type Ref } from 'react';\nimport { ToggleField, type ToggleSize } from '../internal/ToggleField';\nimport styles from './Checkbox.module.css';\n\nexport type CheckboxSize = ToggleSize;\n\nexport interface CheckboxProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'size' | 'type'> {\n /** Visible label beside the box. */\n label: ReactNode;\n description?: ReactNode;\n /** Presence marks the control invalid and announces the message. */\n error?: ReactNode;\n /** @default 'md' */\n size?: CheckboxSize;\n /** The \"some selected\" state; visual and `aria-checked=\"mixed\"`, independent of `checked`. @default false */\n indeterminate?: boolean;\n /** The `<input>` element. */\n ref?: Ref<HTMLInputElement>;\n /** Applied to the wrapper, not the input. */\n className?: string;\n}\n\n/**\n * A native checkbox drawn with tokens: `appearance: none` on the input, the\n * box and tick in CSS, so keyboard, forms and assistive technology are the\n * browser's own. Label, description and error come from Field. Controlled and\n * uncontrolled behave like the native input. State is the native `:checked`\n * and `:indeterminate`, plus `data-indeterminate` on the input.\n *\n * @status stable\n * @category Forms\n * @accessibility A native `input type=\"checkbox\"` with `appearance: none`; label, description and error wire through Field. `indeterminate` sets the DOM property and `aria-checked=\"mixed\"`. Keyboard: Space toggles.\n * @do Use `indeterminate` for a parent whose children are partly selected.\n * Group related checkboxes under a `fieldset`.\n * @dont Use it for an immediate setting; use Switch.\n * Hide the label; the description does not name the control.\n */\nexport function Checkbox({\n label,\n description,\n error,\n size = 'md',\n indeterminate = false,\n required,\n disabled,\n id,\n className,\n ref,\n 'aria-describedby': describedBy,\n ...rest\n}: CheckboxProps) {\n // `indeterminate` is a property, not an attribute: set it on the element as it mounts and whenever it changes.\n const setRef = useCallback(\n (element: HTMLInputElement | null) => {\n if (element) element.indeterminate = indeterminate;\n if (typeof ref === 'function') ref(element);\n else if (ref) ref.current = element;\n },\n [indeterminate, ref],\n );\n\n return (\n <ToggleField\n label={label}\n description={description}\n error={error}\n size={size}\n required={required}\n disabled={disabled}\n id={id}\n className={className}\n rootClassName={styles.checkbox}\n rowClassName={styles.row}\n aria-describedby={describedBy}\n control={\n <input\n {...rest}\n ref={setRef}\n type=\"checkbox\"\n className={styles.input}\n aria-checked={indeterminate ? 'mixed' : undefined}\n data-indeterminate={indeterminate ? '' : undefined}\n />\n }\n />\n );\n}\n\nCheckbox.displayName = 'Checkbox';\n"]}
@@ -1,4 +1,4 @@
1
- import { Field } from './chunk-M5VL22MY.js';
1
+ import { Field } from './chunk-SXMORGSG.js';
2
2
  import { classes } from './chunk-MI4QUKQS.js';
3
3
  import { jsxs, jsx } from 'react/jsx-runtime';
4
4
 
@@ -49,5 +49,5 @@ function Textarea({
49
49
  Textarea.displayName = "Textarea";
50
50
 
51
51
  export { Textarea };
52
- //# sourceMappingURL=chunk-5PYLJQJX.js.map
53
- //# sourceMappingURL=chunk-5PYLJQJX.js.map
52
+ //# sourceMappingURL=chunk-VS2HPJIX.js.map
53
+ //# sourceMappingURL=chunk-VS2HPJIX.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/textarea/Textarea.module.css","../src/textarea/Textarea.tsx"],"names":["field","textarea"],"mappings":";;;;;AAAA,IAAA,gBAAA,GAAA;AAAA,EAKG,KAAA,EAAAA,gBAAAA;AAAA,EAIA,QAAA,EAAAC;AAAA,CAAA;AC6BI,SAAS,QAAA,CAAS;AAAA,EACvB,KAAA;AAAA,EACA,WAAA;AAAA,EACA,KAAA;AAAA,EACA,IAAA,GAAO,IAAA;AAAA,EACP,MAAA,GAAS,UAAA;AAAA,EACT,QAAA,GAAW,KAAA;AAAA,EACX,IAAA,GAAO,CAAA;AAAA,EACP,QAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,EAAA;AAAA,EACA,SAAA;AAAA,EACA,GAAA;AAAA,EACA,kBAAA,EAAoB,WAAA;AAAA,EACpB,GAAG;AACL,CAAA,EAAkB;AAChB,EAAA,MAAM,UAAU,KAAA,KAAU,MAAA,IAAa,UAAU,IAAA,IAAQ,KAAA,KAAU,SAAS,KAAA,KAAU,EAAA;AACtF,EAAA,uBACE,IAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,EAAA;AAAA,MACA,OAAA;AAAA,MACA,QAAA,EAAU,QAAQ,QAAQ,CAAA;AAAA,MAC1B,QAAA,EAAU,QAAQ,QAAQ,CAAA;AAAA,MAC1B,SAAA,EAAW,OAAA,CAAQ,gBAAA,CAAO,KAAA,EAAO,SAAS,CAAA;AAAA,MAC1C,WAAA,EAAW,IAAA;AAAA,MACX,aAAA,EAAa,MAAA;AAAA,MACb,gBAAA,EAAgB,WAAW,EAAA,GAAK,MAAA;AAAA,MAChC,eAAA,EAAe,WAAW,EAAA,GAAK,MAAA;AAAA,MAE/B,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,KAAA,CAAM,KAAA,EAAN,EAAa,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,4BACnB,KAAA,CAAM,OAAA,EAAN,EAAc,kBAAA,EAAkB,aAC/B,QAAA,kBAAA,GAAA,CAAC,UAAA,EAAA,EAAU,GAAG,IAAA,EAAM,KAAU,IAAA,EAAY,QAAA,EAAoB,SAAA,EAAW,gBAAA,CAAO,UAAU,CAAA,EAC5F,CAAA;AAAA,QACC,WAAA,oBAAe,GAAA,CAAC,KAAA,CAAM,WAAA,EAAN,EAAmB,QAAA,EAAA,WAAA,EAAY,CAAA;AAAA,QAC/C,OAAA,oBAAW,GAAA,CAAC,KAAA,CAAM,KAAA,EAAN,EAAa,QAAA,EAAA,KAAA,EAAM;AAAA;AAAA;AAAA,GAClC;AAEJ;AAEA,QAAA,CAAS,WAAA,GAAc,UAAA","file":"chunk-5PYLJQJX.js","sourcesContent":["/* Every value is a token (--textarea-*). Label, description and error come from Field. */\n\n@layer reset, tokens, vendor, base, components, utilities;\n\n@layer components {\n .field {\n font-family: var(--textarea-font-family);\n }\n\n .textarea {\n min-block-size: var(--textarea-min-height);\n padding-block: var(--textarea-padding-block);\n padding-inline: var(--textarea-padding-inline);\n border: var(--size-hairline) solid var(--textarea-border-default);\n border-radius: var(--textarea-radius);\n background-color: var(--textarea-bg);\n color: var(--textarea-fg);\n font-size: var(--textarea-font-size-md);\n line-height: var(--textarea-line-height);\n resize: vertical;\n transition:\n border-color var(--textarea-motion-duration) var(--motion-easing-standard),\n background-color var(--textarea-motion-duration) var(--motion-easing-standard);\n\n &::placeholder {\n color: var(--textarea-placeholder);\n }\n\n &:focus-visible {\n border-color: var(--textarea-border-focus);\n outline: var(--textarea-focus-ring-width) solid var(--textarea-focus-ring);\n outline-offset: var(--textarea-focus-ring-offset);\n }\n\n &:disabled {\n cursor: not-allowed;\n opacity: 0.55;\n }\n\n &:read-only:not(:disabled) {\n background-color: var(--color-surface-sunken);\n }\n\n &:hover:not(:disabled, :focus-visible) {\n border-color: var(--textarea-border-hover);\n }\n }\n\n .field[data-size=\"sm\"] .textarea { font-size: var(--textarea-font-size-sm); }\n .field[data-size=\"lg\"] .textarea { font-size: var(--textarea-font-size-lg); }\n .field[data-resize=\"none\"] .textarea { resize: none; }\n .field[data-resize=\"both\"] .textarea { resize: both; }\n .field[data-auto-grow] .textarea { field-sizing: content; }\n .field[data-invalid] .textarea { border-color: var(--textarea-border-invalid); }\n}\n","import type { ReactNode, Ref, TextareaHTMLAttributes } from 'react';\nimport { Field } from '../field';\nimport { classes } from '../internal/classes';\nimport styles from './Textarea.module.css';\n\nexport type TextareaSize = 'sm' | 'md' | 'lg';\nexport type TextareaResize = 'vertical' | 'none' | 'both';\n\nexport interface TextareaProps extends TextareaHTMLAttributes<HTMLTextAreaElement> {\n /** Visible label. Always rendered. */\n label: ReactNode;\n description?: ReactNode;\n /** Presence marks the control invalid and announces the message. */\n error?: ReactNode;\n /** @default 'md' */\n size?: TextareaSize;\n /** @default 'vertical' */\n resize?: TextareaResize;\n /** Grow with the content (`field-sizing: content`, where supported). @default false */\n autoGrow?: boolean;\n /** The `<textarea>` element. */\n ref?: Ref<HTMLTextAreaElement>;\n /** Applied to the wrapper, not the textarea. */\n className?: string;\n}\n\n/**\n * A multi-line text input on top of Field. Same contract as TextField;\n * its own `--textarea-*` tokens so it can diverge. `rows` sets the initial\n * height; `autoGrow` follows the content in browsers that support\n * `field-sizing`, and falls back to `rows` elsewhere.\n *\n * @status stable\n * @category Forms\n * @accessibility A native `textarea` wired through Field; `autoGrow` uses `field-sizing: content` where supported and falls back to `rows`.\n * @do Set `rows` to the typical length of the answer.\n * @dont Disable `resize` without giving the field enough rows.\n */\nexport function Textarea({\n label,\n description,\n error,\n size = 'md',\n resize = 'vertical',\n autoGrow = false,\n rows = 3,\n required,\n disabled,\n readOnly,\n id,\n className,\n ref,\n 'aria-describedby': describedBy,\n ...rest\n}: TextareaProps) {\n const invalid = error !== undefined && error !== null && error !== false && error !== '';\n return (\n <Field\n id={id}\n invalid={invalid}\n disabled={Boolean(disabled)}\n required={Boolean(required)}\n className={classes(styles.field, className)}\n data-size={size}\n data-resize={resize}\n data-auto-grow={autoGrow ? '' : undefined}\n data-readonly={readOnly ? '' : undefined}\n >\n <Field.Label>{label}</Field.Label>\n <Field.Control aria-describedby={describedBy}>\n <textarea {...rest} ref={ref} rows={rows} readOnly={readOnly} className={styles.textarea} />\n </Field.Control>\n {description && <Field.Description>{description}</Field.Description>}\n {invalid && <Field.Error>{error}</Field.Error>}\n </Field>\n );\n}\n\nTextarea.displayName = 'Textarea';\n"]}
1
+ {"version":3,"sources":["../src/textarea/Textarea.module.css","../src/textarea/Textarea.tsx"],"names":["field","textarea"],"mappings":";;;;;AAAA,IAAA,gBAAA,GAAA;AAAA,EAKG,KAAA,EAAAA,gBAAAA;AAAA,EAIA,QAAA,EAAAC;AAAA,CAAA;AC6BI,SAAS,QAAA,CAAS;AAAA,EACvB,KAAA;AAAA,EACA,WAAA;AAAA,EACA,KAAA;AAAA,EACA,IAAA,GAAO,IAAA;AAAA,EACP,MAAA,GAAS,UAAA;AAAA,EACT,QAAA,GAAW,KAAA;AAAA,EACX,IAAA,GAAO,CAAA;AAAA,EACP,QAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,EAAA;AAAA,EACA,SAAA;AAAA,EACA,GAAA;AAAA,EACA,kBAAA,EAAoB,WAAA;AAAA,EACpB,GAAG;AACL,CAAA,EAAkB;AAChB,EAAA,MAAM,UAAU,KAAA,KAAU,MAAA,IAAa,UAAU,IAAA,IAAQ,KAAA,KAAU,SAAS,KAAA,KAAU,EAAA;AACtF,EAAA,uBACE,IAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,EAAA;AAAA,MACA,OAAA;AAAA,MACA,QAAA,EAAU,QAAQ,QAAQ,CAAA;AAAA,MAC1B,QAAA,EAAU,QAAQ,QAAQ,CAAA;AAAA,MAC1B,SAAA,EAAW,OAAA,CAAQ,gBAAA,CAAO,KAAA,EAAO,SAAS,CAAA;AAAA,MAC1C,WAAA,EAAW,IAAA;AAAA,MACX,aAAA,EAAa,MAAA;AAAA,MACb,gBAAA,EAAgB,WAAW,EAAA,GAAK,MAAA;AAAA,MAChC,eAAA,EAAe,WAAW,EAAA,GAAK,MAAA;AAAA,MAE/B,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,KAAA,CAAM,KAAA,EAAN,EAAa,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,4BACnB,KAAA,CAAM,OAAA,EAAN,EAAc,kBAAA,EAAkB,aAC/B,QAAA,kBAAA,GAAA,CAAC,UAAA,EAAA,EAAU,GAAG,IAAA,EAAM,KAAU,IAAA,EAAY,QAAA,EAAoB,SAAA,EAAW,gBAAA,CAAO,UAAU,CAAA,EAC5F,CAAA;AAAA,QACC,WAAA,oBAAe,GAAA,CAAC,KAAA,CAAM,WAAA,EAAN,EAAmB,QAAA,EAAA,WAAA,EAAY,CAAA;AAAA,QAC/C,OAAA,oBAAW,GAAA,CAAC,KAAA,CAAM,KAAA,EAAN,EAAa,QAAA,EAAA,KAAA,EAAM;AAAA;AAAA;AAAA,GAClC;AAEJ;AAEA,QAAA,CAAS,WAAA,GAAc,UAAA","file":"chunk-VS2HPJIX.js","sourcesContent":["/* Every value is a token (--textarea-*). Label, description and error come from Field. */\n\n@layer reset, tokens, vendor, base, components, utilities;\n\n@layer components {\n .field {\n font-family: var(--textarea-font-family);\n }\n\n .textarea {\n min-block-size: var(--textarea-min-height);\n padding-block: var(--textarea-padding-block);\n padding-inline: var(--textarea-padding-inline);\n border: var(--size-hairline) solid var(--textarea-border-default);\n border-radius: var(--textarea-radius);\n background-color: var(--textarea-bg);\n color: var(--textarea-fg);\n font-size: var(--textarea-font-size-md);\n line-height: var(--textarea-line-height);\n resize: vertical;\n transition:\n border-color var(--textarea-motion-duration) var(--motion-easing-standard),\n background-color var(--textarea-motion-duration) var(--motion-easing-standard);\n\n &::placeholder {\n color: var(--textarea-placeholder);\n }\n\n &:focus-visible {\n border-color: var(--textarea-border-focus);\n outline: var(--textarea-focus-ring-width) solid var(--textarea-focus-ring);\n outline-offset: var(--textarea-focus-ring-offset);\n }\n\n &:disabled {\n cursor: not-allowed;\n opacity: 0.55;\n }\n\n &:read-only:not(:disabled) {\n background-color: var(--color-surface-sunken);\n }\n\n &:hover:not(:disabled, :focus-visible) {\n border-color: var(--textarea-border-hover);\n }\n }\n\n .field[data-size=\"sm\"] .textarea { font-size: var(--textarea-font-size-sm); }\n .field[data-size=\"lg\"] .textarea { font-size: var(--textarea-font-size-lg); }\n .field[data-resize=\"none\"] .textarea { resize: none; }\n .field[data-resize=\"both\"] .textarea { resize: both; }\n .field[data-auto-grow] .textarea { field-sizing: content; }\n .field[data-invalid] .textarea { border-color: var(--textarea-border-invalid); }\n}\n","import type { ReactNode, Ref, TextareaHTMLAttributes } from 'react';\nimport { Field } from '../field';\nimport { classes } from '../internal/classes';\nimport styles from './Textarea.module.css';\n\nexport type TextareaSize = 'sm' | 'md' | 'lg';\nexport type TextareaResize = 'vertical' | 'none' | 'both';\n\nexport interface TextareaProps extends TextareaHTMLAttributes<HTMLTextAreaElement> {\n /** Visible label. Always rendered. */\n label: ReactNode;\n description?: ReactNode;\n /** Presence marks the control invalid and announces the message. */\n error?: ReactNode;\n /** @default 'md' */\n size?: TextareaSize;\n /** @default 'vertical' */\n resize?: TextareaResize;\n /** Grow with the content (`field-sizing: content`, where supported). @default false */\n autoGrow?: boolean;\n /** The `<textarea>` element. */\n ref?: Ref<HTMLTextAreaElement>;\n /** Applied to the wrapper, not the textarea. */\n className?: string;\n}\n\n/**\n * A multi-line text input on top of Field. Same contract as TextField;\n * its own `--textarea-*` tokens so it can diverge. `rows` sets the initial\n * height; `autoGrow` follows the content in browsers that support\n * `field-sizing`, and falls back to `rows` elsewhere.\n *\n * @status stable\n * @category Forms\n * @accessibility A native `textarea` wired through Field; `autoGrow` uses `field-sizing: content` where supported and falls back to `rows`.\n * @do Set `rows` to the typical length of the answer.\n * @dont Disable `resize` without giving the field enough rows.\n */\nexport function Textarea({\n label,\n description,\n error,\n size = 'md',\n resize = 'vertical',\n autoGrow = false,\n rows = 3,\n required,\n disabled,\n readOnly,\n id,\n className,\n ref,\n 'aria-describedby': describedBy,\n ...rest\n}: TextareaProps) {\n const invalid = error !== undefined && error !== null && error !== false && error !== '';\n return (\n <Field\n id={id}\n invalid={invalid}\n disabled={Boolean(disabled)}\n required={Boolean(required)}\n className={classes(styles.field, className)}\n data-size={size}\n data-resize={resize}\n data-auto-grow={autoGrow ? '' : undefined}\n data-readonly={readOnly ? '' : undefined}\n >\n <Field.Label>{label}</Field.Label>\n <Field.Control aria-describedby={describedBy}>\n <textarea {...rest} ref={ref} rows={rows} readOnly={readOnly} className={styles.textarea} />\n </Field.Control>\n {description && <Field.Description>{description}</Field.Description>}\n {invalid && <Field.Error>{error}</Field.Error>}\n </Field>\n );\n}\n\nTextarea.displayName = 'Textarea';\n"]}
@@ -1,6 +1,6 @@
1
1
  import { Spinner } from './chunk-ZL5MMRLG.js';
2
- import { renderOption, renderEmpty, listClass } from './chunk-EDTA65L5.js';
3
2
  import { isPresent, AriaFieldLabel, AriaFieldDescription, AriaFieldError, ariaFieldClass } from './chunk-IRNTXAA7.js';
3
+ import { renderOption, renderEmpty, listClass } from './chunk-EDTA65L5.js';
4
4
  import { Icon } from './chunk-O5LII5XP.js';
5
5
  import { useFilter, ComboBox, Input, Button, Popover, ListBox } from 'react-aria-components';
6
6
  import { ChevronDown } from '@pearpages/pulp-icons';
@@ -82,5 +82,5 @@ function Combobox({
82
82
  Combobox.displayName = "Combobox";
83
83
 
84
84
  export { Combobox };
85
- //# sourceMappingURL=chunk-NOUUOH4R.js.map
86
- //# sourceMappingURL=chunk-NOUUOH4R.js.map
85
+ //# sourceMappingURL=chunk-WDIFWMKE.js.map
86
+ //# sourceMappingURL=chunk-WDIFWMKE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/combobox/Combobox.module.css","../src/combobox/Combobox.tsx"],"names":["root","control","input","button","popover","list","AriaComboBox","AriaInput","AriaButton","AriaPopover","AriaListBox"],"mappings":"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","file":"chunk-WDIFWMKE.js","sourcesContent":["/*\n * Every value is a token (--combobox-*); the options read --listbox-*. Size\n * and invalid state resolve into private custom properties on the root. The\n * popover is positioned by React Aria; the gap to the control is its own\n * padding, so no offset number lives in code, and --trigger-width (set by\n * the vendor) makes it as wide as the control.\n */\n\n@layer reset, tokens, vendor, base, components, utilities;\n\n@layer components {\n .root {\n --_height: var(--combobox-height-md);\n --_font-size: var(--combobox-font-size-md);\n --_border: var(--combobox-border-default);\n\n font-family: var(--combobox-font-family);\n\n &[data-size=\"sm\"] {\n --_height: var(--combobox-height-sm);\n --_font-size: var(--combobox-font-size-sm);\n }\n\n &[data-size=\"lg\"] {\n --_height: var(--combobox-height-lg);\n --_font-size: var(--combobox-font-size-lg);\n }\n\n &[data-invalid] { --_border: var(--combobox-border-invalid); }\n }\n\n .control {\n display: grid;\n align-items: center;\n\n & > * {\n grid-area: 1 / 1;\n }\n }\n\n .input {\n inline-size: 100%;\n min-block-size: var(--_height);\n padding-block: 0;\n padding-inline: var(--combobox-padding-inline) var(--combobox-icon-size);\n border: var(--size-hairline) solid var(--_border);\n border-radius: var(--combobox-radius);\n background-color: var(--combobox-bg);\n color: var(--combobox-fg);\n font-size: var(--_font-size);\n transition: border-color var(--combobox-motion-duration) var(--motion-easing-standard);\n\n &::placeholder {\n color: var(--combobox-placeholder);\n }\n\n &[data-focused] {\n border-color: var(--combobox-border-focus);\n outline: var(--combobox-focus-ring-width) solid var(--combobox-focus-ring);\n outline-offset: var(--combobox-focus-ring-offset);\n }\n\n &[data-disabled] {\n cursor: not-allowed;\n opacity: 0.55;\n }\n\n &[data-hovered]:not([data-focused], [data-disabled]) {\n border-color: var(--combobox-border-hover);\n }\n }\n\n .button {\n display: grid;\n place-items: center;\n inline-size: var(--combobox-icon-size);\n block-size: var(--_height);\n padding: 0;\n border: none;\n border-radius: var(--combobox-radius);\n background-color: transparent;\n color: var(--combobox-icon);\n justify-self: end;\n cursor: pointer;\n\n &[data-focus-visible] {\n outline: var(--combobox-focus-ring-width) solid var(--combobox-focus-ring);\n outline-offset: calc(-1 * var(--combobox-focus-ring-width));\n }\n\n &[data-disabled] {\n cursor: not-allowed;\n }\n }\n\n .popover {\n inline-size: var(--trigger-width);\n padding-block-start: var(--combobox-gap);\n animation: fade var(--combobox-popover-duration) var(--motion-easing-standard);\n\n &[data-placement=\"top\"] {\n padding-block: 0 var(--combobox-gap);\n }\n }\n\n .list {\n box-shadow: var(--combobox-popover-shadow);\n }\n\n /* The shared list styles paint an inline Listbox's surface; here the list floats. Two classes, so it wins whatever the stylesheet order. */\n .popover .list {\n background-color: var(--combobox-popover-bg);\n }\n\n @keyframes fade {\n from {\n opacity: 0;\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n .popover {\n animation: none;\n }\n }\n}\n","import type { ReactNode, Ref } from 'react';\nimport {\n Button as AriaButton,\n ComboBox as AriaComboBox,\n Input as AriaInput,\n ListBox as AriaListBox,\n Popover as AriaPopover,\n useFilter,\n} from 'react-aria-components';\nimport { ChevronDown } from '@pearpages/pulp-icons';\nimport { Icon } from '../icon';\nimport { AriaFieldDescription, AriaFieldError, AriaFieldLabel, ariaFieldClass, isPresent } from '../internal/AriaField';\nimport { listClass, renderEmpty, renderOption, type ListboxItem } from '../listbox/ListboxOptions';\nimport { Spinner } from '../spinner';\nimport styles from './Combobox.module.css';\n\nexport type ComboboxItem = ListboxItem;\nexport type ComboboxSize = 'sm' | 'md' | 'lg';\n/** `contains` and `startsWith` filter `items` as the user types; `none` shows `items` as given (you filtered them, typically after a fetch). */\nexport type ComboboxFilter = 'contains' | 'startsWith' | 'none';\n\nexport interface ComboboxProps {\n /** Visible label. Always rendered. */\n label: ReactNode;\n description?: ReactNode;\n /** Presence marks the control invalid and announces the message. */\n error?: ReactNode;\n /** The options. With `filter=\"none\"` they are shown as given. */\n items: readonly ComboboxItem[];\n /** Selected id (controlled). `null` is \"nothing selected\". */\n value?: string | null;\n defaultValue?: string | null;\n onChange?: (value: string | null) => void;\n /** The text in the input (controlled). Pair with `onInputChange` to fetch options as the user types. */\n inputValue?: string;\n defaultInputValue?: string;\n onInputChange?: (text: string) => void;\n /** @default 'contains' */\n filter?: ComboboxFilter;\n /** Keeps the list open with a spinner in the control while options load. @default false */\n loading?: boolean;\n /** Shown in the open list when no option matches. @default 'No results' */\n emptyMessage?: ReactNode;\n /** Announced while `loading`. @default 'Loading…' */\n loadingMessage?: ReactNode;\n /** Let the typed text stand as the value even when it matches no option. @default false */\n allowsCustomValue?: boolean;\n /** When the list opens: on focus, on typing, or only from the button and arrow keys. @default 'input' */\n menuTrigger?: 'focus' | 'input' | 'manual';\n placeholder?: string;\n /** @default 'md' */\n size?: ComboboxSize;\n /** @default false */\n required?: boolean;\n /** @default false */\n disabled?: boolean;\n /** @default false */\n readOnly?: boolean;\n /** Submitted with a form: the selected id (or the text with `allowsCustomValue`). */\n name?: string;\n autoFocus?: boolean;\n /** Applied to the field wrapper, not the input. */\n className?: string;\n /** The `<input>` element. */\n ref?: Ref<HTMLInputElement>;\n}\n\n/**\n * A text input that suggests options as the user types, on React Aria's\n * combobox (decision record 001): the list is announced through\n * `aria-activedescendant`, arrows move, Enter selects, Escape closes and\n * then clears. Static lists filter themselves; for async options, control\n * `inputValue`, fetch, and pass the results with `filter=\"none\"` and\n * `loading` while they arrive. Options look the same as Listbox's.\n *\n * @status experimental\n * @category Forms\n * @accessibility A `combobox` input with `aria-autocomplete=\"list\"`; the open list is a `listbox` announced through `aria-activedescendant`, so focus stays in the input. Arrows move, Enter selects, Escape closes and then clears. Loading and empty states are announced from inside the list.\n * @do Use `filter=\"none\"` with controlled `inputValue` for server-side search.\n * Keep `loading` true until the results for the current text arrive.\n * @dont Use it for fewer than five fixed options; use Picker or the native Select.\n * Set `menuTrigger=\"focus\"` on a long list; opening on every focus is noisy.\n */\nexport function Combobox({\n label,\n description,\n error,\n items,\n value,\n defaultValue,\n onChange,\n inputValue,\n defaultInputValue,\n onInputChange,\n filter = 'contains',\n loading = false,\n emptyMessage = 'No results',\n loadingMessage = 'Loading…',\n allowsCustomValue = false,\n menuTrigger = 'input',\n placeholder,\n size = 'md',\n required = false,\n disabled = false,\n readOnly = false,\n name,\n autoFocus,\n className,\n ref,\n}: ComboboxProps) {\n const { contains, startsWith } = useFilter({ sensitivity: 'base' });\n const invalid = isPresent(error);\n // `items` means \"already filtered\"; `defaultItems` lets React Aria filter.\n const collection = filter === 'none' ? { items } : { defaultItems: items, defaultFilter: filter === 'startsWith' ? startsWith : contains };\n\n return (\n <AriaComboBox\n {...collection}\n className={ariaFieldClass(styles.root, className)}\n data-size={size}\n data-loading={loading ? '' : undefined}\n selectedKey={value}\n defaultSelectedKey={defaultValue}\n onSelectionChange={(key) => onChange?.(key === null ? null : String(key))}\n inputValue={inputValue}\n defaultInputValue={defaultInputValue}\n onInputChange={onInputChange}\n allowsCustomValue={allowsCustomValue}\n allowsEmptyCollection\n menuTrigger={menuTrigger}\n isRequired={required}\n isDisabled={disabled}\n isReadOnly={readOnly}\n isInvalid={invalid}\n name={name}\n >\n <AriaFieldLabel required={required}>{label}</AriaFieldLabel>\n <div className={styles.control}>\n <AriaInput ref={ref} className={styles.input} placeholder={placeholder} autoFocus={autoFocus} />\n <AriaButton className={styles.button}>\n {loading ? (\n <Spinner size=\"inherit\" tone=\"inherit\" decorative />\n ) : (\n <Icon size=\"inherit\">\n <ChevronDown />\n </Icon>\n )}\n </AriaButton>\n </div>\n <AriaFieldDescription>{description}</AriaFieldDescription>\n <AriaFieldError>{error}</AriaFieldError>\n <AriaPopover className={styles.popover} placement=\"bottom start\">\n <AriaListBox className={listClass(styles.list)} renderEmptyState={() => renderEmpty(loading ? loadingMessage : emptyMessage)}>\n {renderOption}\n </AriaListBox>\n </AriaPopover>\n </AriaComboBox>\n );\n}\n\nCombobox.displayName = 'Combobox';\n"]}