@flanksource/clicky-ui 0.2.15 → 0.2.16

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 (84) hide show
  1. package/dist/components/Combobox.cjs +15 -7
  2. package/dist/components/Combobox.cjs.map +1 -1
  3. package/dist/components/Combobox.d.ts +8 -0
  4. package/dist/components/Combobox.d.ts.map +1 -1
  5. package/dist/components/Combobox.js +15 -7
  6. package/dist/components/Combobox.js.map +1 -1
  7. package/dist/components/DateTimePicker.cjs +3 -0
  8. package/dist/components/DateTimePicker.cjs.map +1 -1
  9. package/dist/components/DateTimePicker.d.ts +6 -2
  10. package/dist/components/DateTimePicker.d.ts.map +1 -1
  11. package/dist/components/DateTimePicker.js +3 -0
  12. package/dist/components/DateTimePicker.js.map +1 -1
  13. package/dist/components/Field.cjs +33 -0
  14. package/dist/components/Field.cjs.map +1 -0
  15. package/dist/components/Field.d.ts +27 -0
  16. package/dist/components/Field.d.ts.map +1 -0
  17. package/dist/components/Field.js +33 -0
  18. package/dist/components/Field.js.map +1 -0
  19. package/dist/components/FilterBar.cjs +41 -14
  20. package/dist/components/FilterBar.cjs.map +1 -1
  21. package/dist/components/FilterBar.d.ts +2 -0
  22. package/dist/components/FilterBar.d.ts.map +1 -1
  23. package/dist/components/FilterBar.js +43 -16
  24. package/dist/components/FilterBar.js.map +1 -1
  25. package/dist/components/MultiSelect.cjs +2 -1
  26. package/dist/components/MultiSelect.cjs.map +1 -1
  27. package/dist/components/MultiSelect.d.ts +5 -1
  28. package/dist/components/MultiSelect.d.ts.map +1 -1
  29. package/dist/components/MultiSelect.js +2 -1
  30. package/dist/components/MultiSelect.js.map +1 -1
  31. package/dist/components/json-schema-form-fields.cjs +15 -8
  32. package/dist/components/json-schema-form-fields.cjs.map +1 -1
  33. package/dist/components/json-schema-form-fields.d.ts.map +1 -1
  34. package/dist/components/json-schema-form-fields.js +15 -8
  35. package/dist/components/json-schema-form-fields.js.map +1 -1
  36. package/dist/components/json-schema-form-types.d.ts +1 -0
  37. package/dist/components/json-schema-form-types.d.ts.map +1 -1
  38. package/dist/components/loading.cjs +4 -4
  39. package/dist/components/loading.cjs.map +1 -1
  40. package/dist/components/loading.d.ts +6 -4
  41. package/dist/components/loading.d.ts.map +1 -1
  42. package/dist/components/loading.js +4 -4
  43. package/dist/components/loading.js.map +1 -1
  44. package/dist/components/use-form.cjs +27 -0
  45. package/dist/components/use-form.cjs.map +1 -0
  46. package/dist/components/use-form.d.ts +30 -0
  47. package/dist/components/use-form.d.ts.map +1 -0
  48. package/dist/components/use-form.js +27 -0
  49. package/dist/components/use-form.js.map +1 -0
  50. package/dist/components.cjs +7 -0
  51. package/dist/components.cjs.map +1 -1
  52. package/dist/components.d.ts +4 -1
  53. package/dist/components.d.ts.map +1 -1
  54. package/dist/components.js +8 -1
  55. package/dist/components.js.map +1 -1
  56. package/dist/data/version-info.cjs +3 -3
  57. package/dist/data/version-info.js +3 -3
  58. package/dist/index.cjs +7 -0
  59. package/dist/index.cjs.map +1 -1
  60. package/dist/index.js +8 -1
  61. package/dist/index.js.map +1 -1
  62. package/dist/overlay/Modal.cjs +27 -23
  63. package/dist/overlay/Modal.cjs.map +1 -1
  64. package/dist/overlay/Modal.d.ts +7 -1
  65. package/dist/overlay/Modal.d.ts.map +1 -1
  66. package/dist/overlay/Modal.js +27 -23
  67. package/dist/overlay/Modal.js.map +1 -1
  68. package/dist/rpc/FilterForm.cjs +4 -4
  69. package/dist/rpc/FilterForm.cjs.map +1 -1
  70. package/dist/rpc/FilterForm.js +4 -4
  71. package/dist/rpc/FilterForm.js.map +1 -1
  72. package/dist/rpc/OperationCatalog.cjs +17 -21
  73. package/dist/rpc/OperationCatalog.cjs.map +1 -1
  74. package/dist/rpc/OperationCatalog.d.ts +3 -3
  75. package/dist/rpc/OperationCatalog.d.ts.map +1 -1
  76. package/dist/rpc/OperationCatalog.js +18 -22
  77. package/dist/rpc/OperationCatalog.js.map +1 -1
  78. package/dist/rpc/formMetadata.cjs +5 -3
  79. package/dist/rpc/formMetadata.cjs.map +1 -1
  80. package/dist/rpc/formMetadata.d.ts.map +1 -1
  81. package/dist/rpc/formMetadata.js +5 -3
  82. package/dist/rpc/formMetadata.js.map +1 -1
  83. package/dist/styles.css +1 -1
  84. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"DateTimePicker.js","sources":["../../src/components/DateTimePicker.tsx"],"sourcesContent":["import { forwardRef, useRef, type InputHTMLAttributes, type ReactNode } from \"react\";\nimport { Icon } from \"../data/Icon\";\nimport { UiCalendar } from \"../icons\";\nimport { cn } from \"../lib/utils\";\n\nexport type DateTimePickerProps = Omit<\n InputHTMLAttributes<HTMLInputElement>,\n \"type\" | \"value\" | \"onChange\"\n> & {\n value?: string;\n onChange?: (value: string) => void;\n className?: string;\n inputClassName?: string;\n buttonClassName?: string;\n openButtonLabel?: string;\n /** Trailing in-field adornment, rendered left of the calendar button. */\n suffix?: ReactNode;\n};\n\nexport const DateTimePicker = forwardRef<HTMLInputElement, DateTimePickerProps>(\n (\n {\n value = \"\",\n onChange,\n className,\n inputClassName,\n buttonClassName,\n openButtonLabel = \"Open time picker\",\n suffix,\n ...props\n },\n ref,\n ) => {\n const visibleRef = useRef<HTMLInputElement | null>(null);\n const pickerRef = useRef<HTMLInputElement | null>(null);\n\n function assignRef(node: HTMLInputElement | null) {\n visibleRef.current = node;\n if (typeof ref === \"function\") {\n ref(node);\n } else if (ref) {\n ref.current = node;\n }\n }\n\n return (\n <div data-jsf-control className={cn(\"relative\", className)}>\n <input\n {...props}\n ref={assignRef}\n type=\"text\"\n value={value}\n className={cn(\n \"h-8 w-full rounded-md border border-input bg-background px-2 pr-8 text-xs outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50\",\n inputClassName,\n )}\n onChange={(event) => onChange?.(event.target.value)}\n />\n <input\n ref={pickerRef}\n type=\"datetime-local\"\n tabIndex={-1}\n aria-hidden=\"true\"\n className=\"pointer-events-none absolute left-0 top-0 h-0 w-0 opacity-0\"\n value={toDateTimeLocalValue(value)}\n onChange={(event) => onChange?.(event.target.value)}\n />\n {suffix && (\n <div className=\"absolute inset-y-0 right-7 flex items-center\">{suffix}</div>\n )}\n <button\n type=\"button\"\n aria-label={openButtonLabel}\n disabled={props.disabled}\n className={cn(\n \"absolute inset-y-0 right-1 inline-flex items-center text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50\",\n buttonClassName,\n )}\n onClick={() => {\n visibleRef.current?.focus();\n pickerRef.current?.showPicker?.();\n }}\n >\n <Icon icon={UiCalendar} className=\"text-sm\" />\n </button>\n </div>\n );\n },\n);\n\nDateTimePicker.displayName = \"DateTimePicker\";\n\nfunction toDateTimeLocalValue(value: string) {\n const trimmed = value.trim();\n if (!trimmed) return \"\";\n if (trimmed === \"now\" || trimmed.startsWith(\"now\")) return \"\";\n\n const withTime = /^\\d{4}-\\d{2}-\\d{2}$/.test(trimmed) ? `${trimmed}T00:00` : trimmed;\n\n return /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}/.test(withTime) ? withTime.slice(0, 16) : \"\";\n}\n"],"names":[],"mappings":";;;;;AAmBO,MAAM,iBAAiB;AAAA,EAC5B,CACE;AAAA,IACE,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,kBAAkB;AAAA,IAClB;AAAA,IACA,GAAG;AAAA,EAAA,GAEL,QACG;AACH,UAAM,aAAa,OAAgC,IAAI;AACvD,UAAM,YAAY,OAAgC,IAAI;AAEtD,aAAS,UAAU,MAA+B;AAChD,iBAAW,UAAU;AACrB,UAAI,OAAO,QAAQ,YAAY;AAC7B,YAAI,IAAI;AAAA,MACV,WAAW,KAAK;AACd,YAAI,UAAU;AAAA,MAChB;AAAA,IACF;AAEA,WACE,qBAAC,SAAI,oBAAgB,MAAC,WAAW,GAAG,YAAY,SAAS,GACvD,UAAA;AAAA,MAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UACE,GAAG;AAAA,UACJ,KAAK;AAAA,UACL,MAAK;AAAA,UACL;AAAA,UACA,WAAW;AAAA,YACT;AAAA,YACA;AAAA,UAAA;AAAA,UAEF,UAAU,CAAC,UAAU,qCAAW,MAAM,OAAO;AAAA,QAAK;AAAA,MAAA;AAAA,MAEpD;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,KAAK;AAAA,UACL,MAAK;AAAA,UACL,UAAU;AAAA,UACV,eAAY;AAAA,UACZ,WAAU;AAAA,UACV,OAAO,qBAAqB,KAAK;AAAA,UACjC,UAAU,CAAC,UAAU,qCAAW,MAAM,OAAO;AAAA,QAAK;AAAA,MAAA;AAAA,MAEnD,UACC,oBAAC,OAAA,EAAI,WAAU,gDAAgD,UAAA,QAAO;AAAA,MAExE;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,cAAY;AAAA,UACZ,UAAU,MAAM;AAAA,UAChB,WAAW;AAAA,YACT;AAAA,YACA;AAAA,UAAA;AAAA,UAEF,SAAS,MAAM;;AACb,6BAAW,YAAX,mBAAoB;AACpB,kCAAU,YAAV,mBAAmB,eAAnB;AAAA,UACF;AAAA,UAEA,UAAA,oBAAC,MAAA,EAAK,MAAM,YAAY,WAAU,UAAA,CAAU;AAAA,QAAA;AAAA,MAAA;AAAA,IAC9C,GACF;AAAA,EAEJ;AACF;AAEA,eAAe,cAAc;AAE7B,SAAS,qBAAqB,OAAe;AAC3C,QAAM,UAAU,MAAM,KAAA;AACtB,MAAI,CAAC,QAAS,QAAO;AACrB,MAAI,YAAY,SAAS,QAAQ,WAAW,KAAK,EAAG,QAAO;AAE3D,QAAM,WAAW,sBAAsB,KAAK,OAAO,IAAI,GAAG,OAAO,WAAW;AAE5E,SAAO,iCAAiC,KAAK,QAAQ,IAAI,SAAS,MAAM,GAAG,EAAE,IAAI;AACnF;"}
1
+ {"version":3,"file":"DateTimePicker.js","sources":["../../src/components/DateTimePicker.tsx"],"sourcesContent":["import { forwardRef, useRef, type InputHTMLAttributes, type ReactNode } from \"react\";\nimport { Icon } from \"../data/Icon\";\nimport { UiCalendar } from \"../icons\";\nimport { cn } from \"../lib/utils\";\n\nexport type DateTimePickerProps = Omit<\n InputHTMLAttributes<HTMLInputElement>,\n // `prefix` is a global HTML attribute typed as string; omit it so our\n // ReactNode adornment prop below is not intersected down to `string & ReactNode`.\n \"type\" | \"value\" | \"onChange\" | \"prefix\"\n> & {\n value?: string;\n onChange?: (value: string) => void;\n className?: string;\n inputClassName?: string;\n buttonClassName?: string;\n openButtonLabel?: string;\n /** Trailing in-field adornment, rendered left of the calendar button. */\n suffix?: ReactNode;\n /** Leading in-field adornment, rendered at the left edge of the input. */\n prefix?: ReactNode;\n};\n\nexport const DateTimePicker = forwardRef<HTMLInputElement, DateTimePickerProps>(\n (\n {\n value = \"\",\n onChange,\n className,\n inputClassName,\n buttonClassName,\n openButtonLabel = \"Open time picker\",\n suffix,\n prefix,\n ...props\n },\n ref,\n ) => {\n const visibleRef = useRef<HTMLInputElement | null>(null);\n const pickerRef = useRef<HTMLInputElement | null>(null);\n\n function assignRef(node: HTMLInputElement | null) {\n visibleRef.current = node;\n if (typeof ref === \"function\") {\n ref(node);\n } else if (ref) {\n ref.current = node;\n }\n }\n\n return (\n <div data-jsf-control className={cn(\"relative\", className)}>\n {prefix && <div className=\"absolute inset-y-0 left-1.5 flex items-center\">{prefix}</div>}\n <input\n {...props}\n ref={assignRef}\n type=\"text\"\n value={value}\n className={cn(\n \"h-8 w-full rounded-md border border-input bg-background px-2 pr-8 text-xs outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50\",\n prefix && \"pl-8\",\n inputClassName,\n )}\n onChange={(event) => onChange?.(event.target.value)}\n />\n <input\n ref={pickerRef}\n type=\"datetime-local\"\n tabIndex={-1}\n aria-hidden=\"true\"\n className=\"pointer-events-none absolute left-0 top-0 h-0 w-0 opacity-0\"\n value={toDateTimeLocalValue(value)}\n onChange={(event) => onChange?.(event.target.value)}\n />\n {suffix && (\n <div className=\"absolute inset-y-0 right-7 flex items-center\">{suffix}</div>\n )}\n <button\n type=\"button\"\n aria-label={openButtonLabel}\n disabled={props.disabled}\n className={cn(\n \"absolute inset-y-0 right-1 inline-flex items-center text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50\",\n buttonClassName,\n )}\n onClick={() => {\n visibleRef.current?.focus();\n pickerRef.current?.showPicker?.();\n }}\n >\n <Icon icon={UiCalendar} className=\"text-sm\" />\n </button>\n </div>\n );\n },\n);\n\nDateTimePicker.displayName = \"DateTimePicker\";\n\nfunction toDateTimeLocalValue(value: string) {\n const trimmed = value.trim();\n if (!trimmed) return \"\";\n if (trimmed === \"now\" || trimmed.startsWith(\"now\")) return \"\";\n\n const withTime = /^\\d{4}-\\d{2}-\\d{2}$/.test(trimmed) ? `${trimmed}T00:00` : trimmed;\n\n return /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}/.test(withTime) ? withTime.slice(0, 16) : \"\";\n}\n"],"names":[],"mappings":";;;;;AAuBO,MAAM,iBAAiB;AAAA,EAC5B,CACE;AAAA,IACE,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,kBAAkB;AAAA,IAClB;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EAAA,GAEL,QACG;AACH,UAAM,aAAa,OAAgC,IAAI;AACvD,UAAM,YAAY,OAAgC,IAAI;AAEtD,aAAS,UAAU,MAA+B;AAChD,iBAAW,UAAU;AACrB,UAAI,OAAO,QAAQ,YAAY;AAC7B,YAAI,IAAI;AAAA,MACV,WAAW,KAAK;AACd,YAAI,UAAU;AAAA,MAChB;AAAA,IACF;AAEA,WACE,qBAAC,SAAI,oBAAgB,MAAC,WAAW,GAAG,YAAY,SAAS,GACtD,UAAA;AAAA,MAAA,UAAU,oBAAC,OAAA,EAAI,WAAU,iDAAiD,UAAA,QAAO;AAAA,MAClF;AAAA,QAAC;AAAA,QAAA;AAAA,UACE,GAAG;AAAA,UACJ,KAAK;AAAA,UACL,MAAK;AAAA,UACL;AAAA,UACA,WAAW;AAAA,YACT;AAAA,YACA,UAAU;AAAA,YACV;AAAA,UAAA;AAAA,UAEF,UAAU,CAAC,UAAU,qCAAW,MAAM,OAAO;AAAA,QAAK;AAAA,MAAA;AAAA,MAEpD;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,KAAK;AAAA,UACL,MAAK;AAAA,UACL,UAAU;AAAA,UACV,eAAY;AAAA,UACZ,WAAU;AAAA,UACV,OAAO,qBAAqB,KAAK;AAAA,UACjC,UAAU,CAAC,UAAU,qCAAW,MAAM,OAAO;AAAA,QAAK;AAAA,MAAA;AAAA,MAEnD,UACC,oBAAC,OAAA,EAAI,WAAU,gDAAgD,UAAA,QAAO;AAAA,MAExE;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,cAAY;AAAA,UACZ,UAAU,MAAM;AAAA,UAChB,WAAW;AAAA,YACT;AAAA,YACA;AAAA,UAAA;AAAA,UAEF,SAAS,MAAM;;AACb,6BAAW,YAAX,mBAAoB;AACpB,kCAAU,YAAV,mBAAmB,eAAnB;AAAA,UACF;AAAA,UAEA,UAAA,oBAAC,MAAA,EAAK,MAAM,YAAY,WAAU,UAAA,CAAU;AAAA,QAAA;AAAA,MAAA;AAAA,IAC9C,GACF;AAAA,EAEJ;AACF;AAEA,eAAe,cAAc;AAE7B,SAAS,qBAAqB,OAAe;AAC3C,QAAM,UAAU,MAAM,KAAA;AACtB,MAAI,CAAC,QAAS,QAAO;AACrB,MAAI,YAAY,SAAS,QAAQ,WAAW,KAAK,EAAG,QAAO;AAE3D,QAAM,WAAW,sBAAsB,KAAK,OAAO,IAAI,GAAG,OAAO,WAAW;AAE5E,SAAO,iCAAiC,KAAK,QAAQ,IAAI,SAAS,MAAM,GAAG,EAAE,IAAI;AACnF;"}
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const jsxRuntime = require("react/jsx-runtime");
4
+ const utils = require("../lib/utils.cjs");
5
+ function Field({
6
+ label,
7
+ htmlFor,
8
+ required,
9
+ error,
10
+ helper,
11
+ className,
12
+ labelClassName,
13
+ onBlur,
14
+ children
15
+ }) {
16
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: utils.cn("flex w-full flex-col gap-1", className), onBlur, children: [
17
+ /* @__PURE__ */ jsxRuntime.jsxs(
18
+ "label",
19
+ {
20
+ htmlFor,
21
+ className: utils.cn("flex min-w-0 items-center gap-1 text-sm font-medium", labelClassName),
22
+ children: [
23
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0", children: label }),
24
+ required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 text-destructive", "aria-hidden": true, children: "*" })
25
+ ]
26
+ }
27
+ ),
28
+ children,
29
+ error ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-destructive", children: error }) : helper ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: helper }) : null
30
+ ] });
31
+ }
32
+ exports.Field = Field;
33
+ //# sourceMappingURL=Field.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Field.cjs","sources":["../../src/components/Field.tsx"],"sourcesContent":["import type { FocusEventHandler, ReactNode } from \"react\";\nimport { cn } from \"../lib/utils\";\n\nexport interface FieldProps {\n /** Field label text (or node). */\n label: ReactNode;\n /** Associates the label with a control by id (optional for non-input controls). */\n htmlFor?: string;\n /** Appends a destructive \"*\" after the label. */\n required?: boolean;\n /**\n * Inline validation message rendered under the control in destructive color.\n * When set it takes the place of `helper`.\n */\n error?: ReactNode;\n /** Muted helper/description text under the control (shown when there's no error). */\n helper?: ReactNode;\n className?: string;\n /** Overrides the label classes (e.g. an uppercase form style). */\n labelClassName?: string;\n /**\n * Fires when focus leaves the field (focusout bubbles), so a form can mark the\n * field touched and reveal its error on blur.\n */\n onBlur?: FocusEventHandler<HTMLDivElement>;\n children: ReactNode;\n}\n\n// Field is the generic label-over-control chrome: a label (with an optional\n// required \"*\"), the control, and an inline error or helper line beneath it.\n// Pair it with useForm for blur/submit-gated error display, or pass `error`\n// directly. The same primitive JsonSchemaForm renders internally, exposed for\n// hand-built forms.\nexport function Field({\n label,\n htmlFor,\n required,\n error,\n helper,\n className,\n labelClassName,\n onBlur,\n children,\n}: FieldProps) {\n return (\n <div className={cn(\"flex w-full flex-col gap-1\", className)} onBlur={onBlur}>\n <label\n htmlFor={htmlFor}\n className={cn(\"flex min-w-0 items-center gap-1 text-sm font-medium\", labelClassName)}\n >\n <span className=\"min-w-0\">{label}</span>\n {required && (\n <span className=\"shrink-0 text-destructive\" aria-hidden>\n *\n </span>\n )}\n </label>\n {children}\n {error ? (\n <p className=\"text-xs text-destructive\">{error}</p>\n ) : helper ? (\n <p className=\"text-xs text-muted-foreground\">{helper}</p>\n ) : null}\n </div>\n );\n}\n"],"names":["cn","jsxs","jsx"],"mappings":";;;;AAiCO,SAAS,MAAM;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAe;AACb,yCACG,OAAA,EAAI,WAAWA,MAAAA,GAAG,8BAA8B,SAAS,GAAG,QAC3D,UAAA;AAAA,IAAAC,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAWD,MAAAA,GAAG,uDAAuD,cAAc;AAAA,QAEnF,UAAA;AAAA,UAAAE,2BAAAA,IAAC,QAAA,EAAK,WAAU,WAAW,UAAA,OAAM;AAAA,UAChC,YACCA,2BAAAA,IAAC,QAAA,EAAK,WAAU,6BAA4B,eAAW,MAAC,UAAA,IAAA,CAExD;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,IAGH;AAAA,IACA,QACCA,2BAAAA,IAAC,KAAA,EAAE,WAAU,4BAA4B,UAAA,MAAA,CAAM,IAC7C,SACFA,2BAAAA,IAAC,KAAA,EAAE,WAAU,iCAAiC,kBAAO,IACnD;AAAA,EAAA,GACN;AAEJ;;"}
@@ -0,0 +1,27 @@
1
+ import { FocusEventHandler, ReactNode } from 'react';
2
+ export interface FieldProps {
3
+ /** Field label text (or node). */
4
+ label: ReactNode;
5
+ /** Associates the label with a control by id (optional for non-input controls). */
6
+ htmlFor?: string;
7
+ /** Appends a destructive "*" after the label. */
8
+ required?: boolean;
9
+ /**
10
+ * Inline validation message rendered under the control in destructive color.
11
+ * When set it takes the place of `helper`.
12
+ */
13
+ error?: ReactNode;
14
+ /** Muted helper/description text under the control (shown when there's no error). */
15
+ helper?: ReactNode;
16
+ className?: string;
17
+ /** Overrides the label classes (e.g. an uppercase form style). */
18
+ labelClassName?: string;
19
+ /**
20
+ * Fires when focus leaves the field (focusout bubbles), so a form can mark the
21
+ * field touched and reveal its error on blur.
22
+ */
23
+ onBlur?: FocusEventHandler<HTMLDivElement>;
24
+ children: ReactNode;
25
+ }
26
+ export declare function Field({ label, htmlFor, required, error, helper, className, labelClassName, onBlur, children, }: FieldProps): import("react/jsx-runtime").JSX.Element;
27
+ //# sourceMappingURL=Field.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Field.d.ts","sourceRoot":"","sources":["../../src/components/Field.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAG1D,MAAM,WAAW,UAAU;IACzB,kCAAkC;IAClC,KAAK,EAAE,SAAS,CAAC;IACjB,mFAAmF;IACnF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,qFAAqF;IACrF,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kEAAkE;IAClE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,MAAM,CAAC,EAAE,iBAAiB,CAAC,cAAc,CAAC,CAAC;IAC3C,QAAQ,EAAE,SAAS,CAAC;CACrB;AAOD,wBAAgB,KAAK,CAAC,EACpB,KAAK,EACL,OAAO,EACP,QAAQ,EACR,KAAK,EACL,MAAM,EACN,SAAS,EACT,cAAc,EACd,MAAM,EACN,QAAQ,GACT,EAAE,UAAU,2CAsBZ"}
@@ -0,0 +1,33 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import { cn } from "../lib/utils.js";
3
+ function Field({
4
+ label,
5
+ htmlFor,
6
+ required,
7
+ error,
8
+ helper,
9
+ className,
10
+ labelClassName,
11
+ onBlur,
12
+ children
13
+ }) {
14
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex w-full flex-col gap-1", className), onBlur, children: [
15
+ /* @__PURE__ */ jsxs(
16
+ "label",
17
+ {
18
+ htmlFor,
19
+ className: cn("flex min-w-0 items-center gap-1 text-sm font-medium", labelClassName),
20
+ children: [
21
+ /* @__PURE__ */ jsx("span", { className: "min-w-0", children: label }),
22
+ required && /* @__PURE__ */ jsx("span", { className: "shrink-0 text-destructive", "aria-hidden": true, children: "*" })
23
+ ]
24
+ }
25
+ ),
26
+ children,
27
+ error ? /* @__PURE__ */ jsx("p", { className: "text-xs text-destructive", children: error }) : helper ? /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: helper }) : null
28
+ ] });
29
+ }
30
+ export {
31
+ Field
32
+ };
33
+ //# sourceMappingURL=Field.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Field.js","sources":["../../src/components/Field.tsx"],"sourcesContent":["import type { FocusEventHandler, ReactNode } from \"react\";\nimport { cn } from \"../lib/utils\";\n\nexport interface FieldProps {\n /** Field label text (or node). */\n label: ReactNode;\n /** Associates the label with a control by id (optional for non-input controls). */\n htmlFor?: string;\n /** Appends a destructive \"*\" after the label. */\n required?: boolean;\n /**\n * Inline validation message rendered under the control in destructive color.\n * When set it takes the place of `helper`.\n */\n error?: ReactNode;\n /** Muted helper/description text under the control (shown when there's no error). */\n helper?: ReactNode;\n className?: string;\n /** Overrides the label classes (e.g. an uppercase form style). */\n labelClassName?: string;\n /**\n * Fires when focus leaves the field (focusout bubbles), so a form can mark the\n * field touched and reveal its error on blur.\n */\n onBlur?: FocusEventHandler<HTMLDivElement>;\n children: ReactNode;\n}\n\n// Field is the generic label-over-control chrome: a label (with an optional\n// required \"*\"), the control, and an inline error or helper line beneath it.\n// Pair it with useForm for blur/submit-gated error display, or pass `error`\n// directly. The same primitive JsonSchemaForm renders internally, exposed for\n// hand-built forms.\nexport function Field({\n label,\n htmlFor,\n required,\n error,\n helper,\n className,\n labelClassName,\n onBlur,\n children,\n}: FieldProps) {\n return (\n <div className={cn(\"flex w-full flex-col gap-1\", className)} onBlur={onBlur}>\n <label\n htmlFor={htmlFor}\n className={cn(\"flex min-w-0 items-center gap-1 text-sm font-medium\", labelClassName)}\n >\n <span className=\"min-w-0\">{label}</span>\n {required && (\n <span className=\"shrink-0 text-destructive\" aria-hidden>\n *\n </span>\n )}\n </label>\n {children}\n {error ? (\n <p className=\"text-xs text-destructive\">{error}</p>\n ) : helper ? (\n <p className=\"text-xs text-muted-foreground\">{helper}</p>\n ) : null}\n </div>\n );\n}\n"],"names":[],"mappings":";;AAiCO,SAAS,MAAM;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAe;AACb,8BACG,OAAA,EAAI,WAAW,GAAG,8BAA8B,SAAS,GAAG,QAC3D,UAAA;AAAA,IAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAW,GAAG,uDAAuD,cAAc;AAAA,QAEnF,UAAA;AAAA,UAAA,oBAAC,QAAA,EAAK,WAAU,WAAW,UAAA,OAAM;AAAA,UAChC,YACC,oBAAC,QAAA,EAAK,WAAU,6BAA4B,eAAW,MAAC,UAAA,IAAA,CAExD;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,IAGH;AAAA,IACA,QACC,oBAAC,KAAA,EAAE,WAAU,4BAA4B,UAAA,MAAA,CAAM,IAC7C,SACF,oBAAC,KAAA,EAAE,WAAU,iCAAiC,kBAAO,IACnD;AAAA,EAAA,GACN;AAEJ;"}
@@ -25,6 +25,10 @@ const FILTER_BAR_OVERFLOW_TRIGGER_ESTIMATE_PX = 44;
25
25
  const FilterBarContext = react.createContext({
26
26
  autoSubmit: true
27
27
  });
28
+ function applyFilterExtensions(filter, extensions) {
29
+ if (!extensions || extensions.length === 0) return filter;
30
+ return extensions.reduce((current, ext) => ext(current), filter);
31
+ }
28
32
  function FilterBar({
29
33
  search,
30
34
  filters,
@@ -365,7 +369,13 @@ function OverflowFiltersMenu({
365
369
  className: "flex min-w-0 items-center gap-1 truncate text-[10px] font-medium uppercase tracking-wide text-muted-foreground",
366
370
  title: filter.description ?? filter.label,
367
371
  children: [
368
- /* @__PURE__ */ jsxRuntime.jsx(Icon.LabelIcon, { icon: filter.icon, className: "text-[12px] normal-case" }),
372
+ /* @__PURE__ */ jsxRuntime.jsx(
373
+ Icon.LabelIcon,
374
+ {
375
+ icon: sizedIcon(filter.icon, 12),
376
+ className: "text-[12px] normal-case"
377
+ }
378
+ ),
369
379
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: filter.label })
370
380
  ]
371
381
  }
@@ -476,7 +486,7 @@ function TextFilterValueControl({ filter }) {
476
486
  type: "text",
477
487
  "aria-label": filter.label,
478
488
  className: valueInputClassName(filter.disabled),
479
- placeholder: filter.placeholder ?? "Filter...",
489
+ ...filter.placeholder !== void 0 ? { placeholder: filter.placeholder } : {},
480
490
  value: draft,
481
491
  disabled: filter.disabled,
482
492
  onChange: (event) => setDraft(event.target.value)
@@ -561,7 +571,7 @@ function EnumFilterValueControl({ filter }) {
561
571
  value: filter.value,
562
572
  onChange: filter.onChange,
563
573
  allowCustomValue: false,
564
- placeholder: filter.placeholder ?? `Any ${filter.label.toLowerCase()}`,
574
+ ...filter.placeholder !== void 0 ? { placeholder: filter.placeholder } : {},
565
575
  className: "w-full",
566
576
  ...filter.disabled !== void 0 ? { disabled: filter.disabled } : {}
567
577
  }
@@ -588,7 +598,8 @@ function SelectMultiFilterValueControl({ filter }) {
588
598
  options: filter.options,
589
599
  value: filter.value,
590
600
  onChange: filter.onChange,
591
- placeholder: filter.placeholder ?? `Any ${filter.label.toLowerCase()}`,
601
+ ariaLabel: `${filter.label} filter`,
602
+ ...filter.placeholder !== void 0 ? { placeholder: filter.placeholder } : {},
592
603
  ...filter.disabled !== void 0 ? { disabled: filter.disabled } : {},
593
604
  triggerClassName: "h-8 w-full rounded-md border border-input bg-background px-2 text-sm shadow-none",
594
605
  menuClassName: "left-auto right-0"
@@ -633,12 +644,12 @@ function EnumFilterField({ filter, grow }) {
633
644
  return /* @__PURE__ */ jsxRuntime.jsx(
634
645
  Combobox.Combobox,
635
646
  {
636
- label: filter.label,
647
+ ...comboboxLabelProps(filter),
637
648
  options: enumOptionsToCombobox(filter.options),
638
649
  value: filter.value,
639
650
  onChange: filter.onChange,
640
651
  allowCustomValue: false,
641
- placeholder: filter.placeholder ?? `Any ${filter.label.toLowerCase()}`,
652
+ ...filter.placeholder !== void 0 ? { placeholder: filter.placeholder } : {},
642
653
  className: utils.cn(lookupFieldWidthClass(grow), filter.className),
643
654
  ...filter.disabled !== void 0 ? { disabled: filter.disabled } : {}
644
655
  }
@@ -717,7 +728,7 @@ function TextFilterField({ filter, grow }) {
717
728
  type: "text",
718
729
  "aria-label": filter.label,
719
730
  className: "w-full min-w-0 bg-transparent text-sm text-foreground outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed",
720
- placeholder: filter.placeholder ?? "Filter…",
731
+ ...filter.placeholder !== void 0 ? { placeholder: filter.placeholder } : {},
721
732
  value: draft,
722
733
  disabled: filter.disabled,
723
734
  onChange: (event) => setDraft(event.target.value)
@@ -733,6 +744,20 @@ function FilterFieldLabel({ icon, label }) {
733
744
  label
734
745
  ] });
735
746
  }
747
+ function sizedIcon(icon, px) {
748
+ if (!react.isValidElement(icon)) return icon;
749
+ const el = icon;
750
+ return react.cloneElement(el, {
751
+ style: { width: `${px}px`, height: `${px}px`, ...el.props.style ?? {} }
752
+ });
753
+ }
754
+ function comboboxLabelProps(filter) {
755
+ if (filter.icon == null) return { label: filter.label };
756
+ return {
757
+ label: /* @__PURE__ */ jsxRuntime.jsx("span", { title: filter.label, className: "inline-flex items-center text-[10px]", children: /* @__PURE__ */ jsxRuntime.jsx(Icon.LabelIcon, { icon: sizedIcon(filter.icon, 10), className: "normal-case" }) }),
758
+ ariaLabel: filter.label
759
+ };
760
+ }
736
761
  function lookupFieldWidthClass(grow) {
737
762
  return grow ? "min-w-[12rem] max-w-[18rem] flex-1" : "min-w-[11rem] max-w-[15rem] shrink-0";
738
763
  }
@@ -783,7 +808,7 @@ function LookupFilterField({ filter, grow }) {
783
808
  return /* @__PURE__ */ jsxRuntime.jsx(
784
809
  Combobox.Combobox,
785
810
  {
786
- label: filter.label,
811
+ ...comboboxLabelProps(filter),
787
812
  options: lookupOptionsToCombobox(filter.options),
788
813
  value: filter.value,
789
814
  onChange: filter.onChange,
@@ -802,7 +827,7 @@ function LookupMultiFilterField({
802
827
  Combobox.Combobox,
803
828
  {
804
829
  multiple: true,
805
- label: filter.label,
830
+ ...comboboxLabelProps(filter),
806
831
  options: lookupOptionsToCombobox(filter.options),
807
832
  value: filter.value,
808
833
  onChange: filter.onChange,
@@ -910,7 +935,7 @@ function NumberFilterField({ filter, grow }) {
910
935
  step: bounds.step,
911
936
  "aria-label": `${filter.label} minimum`,
912
937
  className: "h-8 w-full rounded-md border border-input bg-background px-2 text-xs outline-none focus-visible:ring-2 focus-visible:ring-ring",
913
- placeholder: filter.minPlaceholder ?? formatNumberValue(bounds.min, filter),
938
+ ...filter.minPlaceholder !== void 0 ? { placeholder: filter.minPlaceholder } : {},
914
939
  value: draft.min ?? "",
915
940
  onChange: (event) => setDraft(
916
941
  normalizeNumberFilterValue(
@@ -931,7 +956,7 @@ function NumberFilterField({ filter, grow }) {
931
956
  step: bounds.step,
932
957
  "aria-label": `${filter.label} maximum`,
933
958
  className: "h-8 w-full rounded-md border border-input bg-background px-2 text-xs outline-none focus-visible:ring-2 focus-visible:ring-ring",
934
- placeholder: filter.maxPlaceholder ?? formatNumberValue(bounds.max, filter),
959
+ ...filter.maxPlaceholder !== void 0 ? { placeholder: filter.maxPlaceholder } : {},
935
960
  value: draft.max ?? "",
936
961
  onChange: (event) => setDraft(
937
962
  normalizeNumberFilterValue(
@@ -1015,7 +1040,7 @@ function NumberFilterPanel({
1015
1040
  step: bounds.step,
1016
1041
  "aria-label": `${filter.label} minimum`,
1017
1042
  className: "h-8 w-full rounded-md border border-input bg-background px-2 text-xs outline-none focus-visible:ring-2 focus-visible:ring-ring",
1018
- placeholder: filter.minPlaceholder ?? formatNumberValue(bounds.min, filter),
1043
+ ...filter.minPlaceholder !== void 0 ? { placeholder: filter.minPlaceholder } : {},
1019
1044
  value: draft.min ?? "",
1020
1045
  onChange: (event) => setDraft(
1021
1046
  normalizeNumberFilterValue(
@@ -1036,7 +1061,7 @@ function NumberFilterPanel({
1036
1061
  step: bounds.step,
1037
1062
  "aria-label": `${filter.label} maximum`,
1038
1063
  className: "h-8 w-full rounded-md border border-input bg-background px-2 text-xs outline-none focus-visible:ring-2 focus-visible:ring-ring",
1039
- placeholder: filter.maxPlaceholder ?? formatNumberValue(bounds.max, filter),
1064
+ ...filter.maxPlaceholder !== void 0 ? { placeholder: filter.maxPlaceholder } : {},
1040
1065
  value: draft.max ?? "",
1041
1066
  onChange: (event) => setDraft(
1042
1067
  normalizeNumberFilterValue(
@@ -1732,7 +1757,8 @@ function SelectMultiFilterField({
1732
1757
  options: filter.options,
1733
1758
  value: filter.value,
1734
1759
  onChange: filter.onChange,
1735
- placeholder: filter.placeholder ?? `Any ${filter.label.toLowerCase()}`,
1760
+ ariaLabel: `${filter.label} filter`,
1761
+ ...filter.placeholder !== void 0 ? { placeholder: filter.placeholder } : {},
1736
1762
  ...filter.disabled !== void 0 ? { disabled: filter.disabled } : {},
1737
1763
  triggerClassName: "h-6 min-w-0 border-0 bg-transparent px-1 text-xs shadow-none focus-visible:ring-0",
1738
1764
  menuClassName: "left-auto right-0"
@@ -2111,4 +2137,5 @@ function estimateFilterWidth(filter) {
2111
2137
  exports.FilterBar = FilterBar;
2112
2138
  exports.FilterBarFilterPanel = FilterBarFilterPanel;
2113
2139
  exports.FilterBarRangePanel = FilterBarRangePanel;
2140
+ exports.applyFilterExtensions = applyFilterExtensions;
2114
2141
  //# sourceMappingURL=FilterBar.cjs.map