@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.
- package/dist/components/Combobox.cjs +15 -7
- package/dist/components/Combobox.cjs.map +1 -1
- package/dist/components/Combobox.d.ts +8 -0
- package/dist/components/Combobox.d.ts.map +1 -1
- package/dist/components/Combobox.js +15 -7
- package/dist/components/Combobox.js.map +1 -1
- package/dist/components/DateTimePicker.cjs +3 -0
- package/dist/components/DateTimePicker.cjs.map +1 -1
- package/dist/components/DateTimePicker.d.ts +6 -2
- package/dist/components/DateTimePicker.d.ts.map +1 -1
- package/dist/components/DateTimePicker.js +3 -0
- package/dist/components/DateTimePicker.js.map +1 -1
- package/dist/components/Field.cjs +33 -0
- package/dist/components/Field.cjs.map +1 -0
- package/dist/components/Field.d.ts +27 -0
- package/dist/components/Field.d.ts.map +1 -0
- package/dist/components/Field.js +33 -0
- package/dist/components/Field.js.map +1 -0
- package/dist/components/FilterBar.cjs +41 -14
- package/dist/components/FilterBar.cjs.map +1 -1
- package/dist/components/FilterBar.d.ts +2 -0
- package/dist/components/FilterBar.d.ts.map +1 -1
- package/dist/components/FilterBar.js +43 -16
- package/dist/components/FilterBar.js.map +1 -1
- package/dist/components/MultiSelect.cjs +2 -1
- package/dist/components/MultiSelect.cjs.map +1 -1
- package/dist/components/MultiSelect.d.ts +5 -1
- package/dist/components/MultiSelect.d.ts.map +1 -1
- package/dist/components/MultiSelect.js +2 -1
- package/dist/components/MultiSelect.js.map +1 -1
- package/dist/components/json-schema-form-fields.cjs +15 -8
- package/dist/components/json-schema-form-fields.cjs.map +1 -1
- package/dist/components/json-schema-form-fields.d.ts.map +1 -1
- package/dist/components/json-schema-form-fields.js +15 -8
- package/dist/components/json-schema-form-fields.js.map +1 -1
- package/dist/components/json-schema-form-types.d.ts +1 -0
- package/dist/components/json-schema-form-types.d.ts.map +1 -1
- package/dist/components/loading.cjs +4 -4
- package/dist/components/loading.cjs.map +1 -1
- package/dist/components/loading.d.ts +6 -4
- package/dist/components/loading.d.ts.map +1 -1
- package/dist/components/loading.js +4 -4
- package/dist/components/loading.js.map +1 -1
- package/dist/components/use-form.cjs +27 -0
- package/dist/components/use-form.cjs.map +1 -0
- package/dist/components/use-form.d.ts +30 -0
- package/dist/components/use-form.d.ts.map +1 -0
- package/dist/components/use-form.js +27 -0
- package/dist/components/use-form.js.map +1 -0
- package/dist/components.cjs +7 -0
- package/dist/components.cjs.map +1 -1
- package/dist/components.d.ts +4 -1
- package/dist/components.d.ts.map +1 -1
- package/dist/components.js +8 -1
- package/dist/components.js.map +1 -1
- package/dist/data/version-info.cjs +3 -3
- package/dist/data/version-info.js +3 -3
- package/dist/index.cjs +7 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +8 -1
- package/dist/index.js.map +1 -1
- package/dist/overlay/Modal.cjs +27 -23
- package/dist/overlay/Modal.cjs.map +1 -1
- package/dist/overlay/Modal.d.ts +7 -1
- package/dist/overlay/Modal.d.ts.map +1 -1
- package/dist/overlay/Modal.js +27 -23
- package/dist/overlay/Modal.js.map +1 -1
- package/dist/rpc/FilterForm.cjs +4 -4
- package/dist/rpc/FilterForm.cjs.map +1 -1
- package/dist/rpc/FilterForm.js +4 -4
- package/dist/rpc/FilterForm.js.map +1 -1
- package/dist/rpc/OperationCatalog.cjs +17 -21
- package/dist/rpc/OperationCatalog.cjs.map +1 -1
- package/dist/rpc/OperationCatalog.d.ts +3 -3
- package/dist/rpc/OperationCatalog.d.ts.map +1 -1
- package/dist/rpc/OperationCatalog.js +18 -22
- package/dist/rpc/OperationCatalog.js.map +1 -1
- package/dist/rpc/formMetadata.cjs +5 -3
- package/dist/rpc/formMetadata.cjs.map +1 -1
- package/dist/rpc/formMetadata.d.ts.map +1 -1
- package/dist/rpc/formMetadata.js +5 -3
- package/dist/rpc/formMetadata.js.map +1 -1
- package/dist/styles.css +1 -1
- 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":";;;;;
|
|
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(
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|