@lattice-php/lattice 0.36.0 → 0.37.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.
- package/dist/chat/components/prompt-input.js +1 -0
- package/dist/chat/components/prompt-input.js.map +1 -1
- package/dist/form/components/base/field.d.ts +14 -4
- package/dist/form/components/base/field.js +33 -10
- package/dist/form/components/base/field.js.map +1 -1
- package/dist/form/components/fields/builder.js +4 -2
- package/dist/form/components/fields/builder.js.map +1 -1
- package/dist/form/components/fields/choice.js +6 -5
- package/dist/form/components/fields/choice.js.map +1 -1
- package/dist/form/components/fields/color-picker-field.js +2 -2
- package/dist/form/components/fields/color-picker-field.js.map +1 -1
- package/dist/form/components/fields/date-input.js +2 -1
- package/dist/form/components/fields/date-input.js.map +1 -1
- package/dist/form/components/fields/date-picker-field.d.ts +3 -1
- package/dist/form/components/fields/date-picker-field.js +2 -2
- package/dist/form/components/fields/date-picker-field.js.map +1 -1
- package/dist/form/components/fields/date-time-input.js +2 -1
- package/dist/form/components/fields/date-time-input.js.map +1 -1
- package/dist/form/components/fields/file-upload.js +4 -4
- package/dist/form/components/fields/file-upload.js.map +1 -1
- package/dist/form/components/fields/number-input.js +3 -3
- package/dist/form/components/fields/number-input.js.map +1 -1
- package/dist/form/components/fields/otp-input.js +2 -2
- package/dist/form/components/fields/otp-input.js.map +1 -1
- package/dist/form/components/fields/password-input.js +6 -6
- package/dist/form/components/fields/password-input.js.map +1 -1
- package/dist/form/components/fields/repeater.js +4 -2
- package/dist/form/components/fields/repeater.js.map +1 -1
- package/dist/form/components/fields/rich-editor-field.js +7 -5
- package/dist/form/components/fields/rich-editor-field.js.map +1 -1
- package/dist/form/components/fields/select.js +5 -5
- package/dist/form/components/fields/select.js.map +1 -1
- package/dist/form/components/fields/simple-field.d.ts +2 -1
- package/dist/form/components/fields/simple-field.js +2 -2
- package/dist/form/components/fields/simple-field.js.map +1 -1
- package/dist/form/components/fields/text-input.js +2 -2
- package/dist/form/components/fields/text-input.js.map +1 -1
- package/dist/form/components/fields/textarea.js +2 -2
- package/dist/form/components/fields/textarea.js.map +1 -1
- package/dist/form/components/fields/time-input.js +2 -2
- package/dist/form/components/fields/time-input.js.map +1 -1
- package/dist/form/components/fields/toggle.js +6 -6
- package/dist/form/components/fields/toggle.js.map +1 -1
- package/dist/form/index.d.ts +1 -0
- package/dist/form/index.js +2 -1
- package/dist/form/toolkit.d.ts +1 -1
- package/dist/lattice.css +16 -0
- package/dist/table/components/column-visibility-menu.js +1 -1
- package/dist/table/components/filter-controls.js +1 -1
- package/dist/table/components/filter-value-input.js +1 -1
- package/dist/table/components/table-search.js +1 -1
- package/dist/types/generated.d.ts +10 -2
- package/dist/ui/code-block-view.d.ts +3 -0
- package/dist/ui/code-block-view.js +115 -0
- package/dist/ui/code-block-view.js.map +1 -0
- package/dist/ui/code-block.d.ts +22 -0
- package/dist/ui/code-block.js +43 -0
- package/dist/ui/code-block.js.map +1 -0
- package/dist/ui/copyable-text.d.ts +3 -1
- package/dist/ui/copyable-text.js +19 -13
- package/dist/ui/copyable-text.js.map +1 -1
- package/dist/ui/index.d.ts +3 -0
- package/dist/ui/index.js +3 -1
- package/dist/ui/plugin.js +2 -0
- package/dist/ui/plugin.js.map +1 -1
- package/dist/ui/segmented-pills.d.ts +2 -1
- package/dist/ui/segmented-pills.js +3 -2
- package/dist/ui/segmented-pills.js.map +1 -1
- package/dist/vite.js.map +1 -1
- package/dist-standalone/chunks/{chart-view-CR1X2aGE.js → chart-view-CFV7BU_D.js} +17 -17
- package/dist-standalone/chunks/code-block-view-D464jtHN.js +34 -0
- package/dist-standalone/chunks/date-picker-field-DepKtR_m.js +1 -0
- package/dist-standalone/chunks/dist-BtOmkEqQ.js +1 -0
- package/dist-standalone/chunks/jsx-runtime-0vZSBttN.js +1 -0
- package/dist-standalone/chunks/{jsx-runtime-CN5ucv1d.js → react-dom-DJCfT20h.js} +1 -1
- package/dist-standalone/chunks/rich-editor-field-BZQIPOLc.js +158 -0
- package/dist-standalone/chunks/{subscriptions-BV4g0s0U.js → subscriptions-4IpkpPX3.js} +1 -1
- package/dist-standalone/chunks/{time-picker-kbhOHEPd.js → time-picker-DUjYyeeP.js} +1 -1
- package/dist-standalone/chunks/use-dependent-field-DvH7mUyx.js +41 -0
- package/dist-standalone/chunks/use-effect-dispatcher-BMWOfaFE.js +97 -0
- package/dist-standalone/chunks/w3c-keyname-BOAvb0qz.js +1 -0
- package/dist-standalone/lattice.css +1 -1
- package/dist-standalone/lattice.js +4 -4
- package/dist-standalone/manifest.json +1 -1
- package/package.json +9 -1
- package/dist-standalone/chunks/date-picker-field-B4Xzow-A.js +0 -1
- package/dist-standalone/chunks/dist-ci5ng714.js +0 -1
- package/dist-standalone/chunks/icon-button-D3AltHNz.js +0 -41
- package/dist-standalone/chunks/rich-editor-field-JM3jBEV1.js +0 -158
- package/dist-standalone/chunks/use-effect-dispatcher-CJXFkAv1.js +0 -97
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toggle.js","names":[],"sources":["../../../../resources/js/form/components/fields/toggle.tsx"],"sourcesContent":["import type { RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport { testIdentity } from \"@lattice-php/lattice/core/test-id\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { FormFieldFrame } from \"@lattice-php/lattice/form/components/base/field\";\nimport { toBoolean } from \"@lattice-php/lattice/form/lib/conditions\";\nimport { useFormContext } from \"@lattice-php/lattice/form/hooks/context\";\nimport { fieldDomName } from \"@lattice-php/lattice/form/lib/field-dom-name\";\nimport { useFieldScope } from \"@lattice-php/lattice/form/hooks/field-scope\";\nimport { useDependentField } from \"@lattice-php/lattice/form/hooks/use-dependent-field\";\nimport { useFieldCommit } from \"@lattice-php/lattice/form/hooks/use-field-commit\";\nimport { useSeedDefault } from \"@lattice-php/lattice/form/hooks/use-seed-default\";\nimport { useFormValue } from \"@lattice-php/lattice/form/hooks/values\";\n\nexport const ToggleComponent: RendererComponent<\"field.toggle\"> = ({ node }) => {\n const { hidden, required, readOnly, disabled } = useDependentField(node);\n const props = node.props;\n const localName = props.name;\n const scope = useFieldScope();\n const { errors, fieldIdPrefix } = useFormContext();\n const name = fieldDomName(scope ? scope.scopedName(localName) : localName, fieldIdPrefix);\n const errorKey = scope ? scope.errorKey(localName) : localName;\n const globalValue = useFormValue(localName);\n const storedValue = scope ? scope.getValue(localName) : globalValue;\n const defaultChecked = toBoolean(props.value);\n const checked = storedValue !== undefined ? toBoolean(storedValue) : defaultChecked;\n const locked = readOnly || disabled;\n const { commit } = useFieldCommit();\n\n useSeedDefault(localName, defaultChecked);\n\n if (hidden) {\n return null;\n }\n\n return (\n <FormFieldFrame\n error={errors[errorKey]}\n helperText={props.helperText ?? undefined}\n tooltip={props.tooltip ?? undefined}\n label={props.label ?? \"\"}\n
|
|
1
|
+
{"version":3,"file":"toggle.js","names":[],"sources":["../../../../resources/js/form/components/fields/toggle.tsx"],"sourcesContent":["import type { RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport { testIdentity } from \"@lattice-php/lattice/core/test-id\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { FormFieldFrame } from \"@lattice-php/lattice/form/components/base/field\";\nimport { toBoolean } from \"@lattice-php/lattice/form/lib/conditions\";\nimport { useFormContext } from \"@lattice-php/lattice/form/hooks/context\";\nimport { fieldDomName } from \"@lattice-php/lattice/form/lib/field-dom-name\";\nimport { useFieldScope } from \"@lattice-php/lattice/form/hooks/field-scope\";\nimport { useDependentField } from \"@lattice-php/lattice/form/hooks/use-dependent-field\";\nimport { useFieldCommit } from \"@lattice-php/lattice/form/hooks/use-field-commit\";\nimport { useSeedDefault } from \"@lattice-php/lattice/form/hooks/use-seed-default\";\nimport { useFormValue } from \"@lattice-php/lattice/form/hooks/values\";\n\nexport const ToggleComponent: RendererComponent<\"field.toggle\"> = ({ node }) => {\n const { hidden, required, readOnly, disabled } = useDependentField(node);\n const props = node.props;\n const localName = props.name;\n const scope = useFieldScope();\n const { errors, fieldIdPrefix } = useFormContext();\n const name = fieldDomName(scope ? scope.scopedName(localName) : localName, fieldIdPrefix);\n const errorKey = scope ? scope.errorKey(localName) : localName;\n const globalValue = useFormValue(localName);\n const storedValue = scope ? scope.getValue(localName) : globalValue;\n const defaultChecked = toBoolean(props.value);\n const checked = storedValue !== undefined ? toBoolean(storedValue) : defaultChecked;\n const locked = readOnly || disabled;\n const { commit } = useFieldCommit();\n\n useSeedDefault(localName, defaultChecked);\n\n if (hidden) {\n return null;\n }\n\n return (\n <FormFieldFrame\n error={errors[errorKey]}\n helperText={props.helperText ?? undefined}\n tooltip={props.tooltip ?? undefined}\n label={props.label ?? \"\"}\n id={name}\n required={required}\n >\n {(controlProps) => (\n <>\n <input disabled={locked} name={name} type=\"hidden\" value={checked ? \"1\" : \"0\"} />\n <button\n {...controlProps}\n aria-checked={checked}\n aria-label={props.label ?? localName}\n autoFocus={props.autoFocus ?? false}\n className={cn(\n \"inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border border-transparent bg-lt-muted p-0.5 shadow-lt-xs transition-colors outline-none focus-visible:border-lt-ring focus-visible:ring-[length:var(--lt-ring-width)] focus-visible:ring-lt-ring/50 disabled:cursor-not-allowed disabled:bg-lt-disabled data-[state=checked]:bg-lt-primary disabled:data-[state=checked]:bg-lt-disabled\",\n )}\n data-state={checked ? \"checked\" : \"unchecked\"}\n data-test={testIdentity(localName)}\n disabled={locked}\n name={name}\n onClick={() => commit(localName, !checked)}\n role=\"switch\"\n tabIndex={props.tabIndex ?? undefined}\n type=\"button\"\n >\n <span\n className=\"size-5 rounded-full bg-lt-bg shadow-lt-sm transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0\"\n data-state={checked ? \"checked\" : \"unchecked\"}\n />\n </button>\n </>\n )}\n </FormFieldFrame>\n );\n};\n"],"mappings":";;;;;;;;;;;;;AAaA,IAAa,mBAAsD,EAAE,WAAW;CAC9E,MAAM,EAAE,QAAQ,UAAU,UAAU,aAAa,kBAAkB,IAAI;CACvE,MAAM,QAAQ,KAAK;CACnB,MAAM,YAAY,MAAM;CACxB,MAAM,QAAQ,cAAc;CAC5B,MAAM,EAAE,QAAQ,kBAAkB,eAAe;CACjD,MAAM,OAAO,aAAa,QAAQ,MAAM,WAAW,SAAS,IAAI,WAAW,aAAa;CACxF,MAAM,WAAW,QAAQ,MAAM,SAAS,SAAS,IAAI;CACrD,MAAM,cAAc,aAAa,SAAS;CAC1C,MAAM,cAAc,QAAQ,MAAM,SAAS,SAAS,IAAI;CACxD,MAAM,iBAAiB,UAAU,MAAM,KAAK;CAC5C,MAAM,UAAU,gBAAgB,KAAA,IAAY,UAAU,WAAW,IAAI;CACrE,MAAM,SAAS,YAAY;CAC3B,MAAM,EAAE,WAAW,eAAe;CAElC,eAAe,WAAW,cAAc;CAExC,IAAI,QACF,OAAO;CAGT,OACE,oBAAC,gBAAD;EACE,OAAO,OAAO;EACd,YAAY,MAAM,cAAc,KAAA;EAChC,SAAS,MAAM,WAAW,KAAA;EAC1B,OAAO,MAAM,SAAS;EACtB,IAAI;EACM;EAER,WAAA,iBACA,qBAAA,UAAA,EAAA,UAAA,CACE,oBAAC,SAAD;GAAO,UAAU;GAAc;GAAM,MAAK;GAAS,OAAO,UAAU,MAAM;EAAM,CAAA,GAChF,oBAAC,UAAD;GACE,GAAI;GACJ,gBAAc;GACd,cAAY,MAAM,SAAS;GAC3B,WAAW,MAAM,aAAa;GAC9B,WAAW,GACT,gZACF;GACA,cAAY,UAAU,YAAY;GAClC,aAAW,aAAa,SAAS;GACjC,UAAU;GACJ;GACN,eAAe,OAAO,WAAW,CAAC,OAAO;GACzC,MAAK;GACL,UAAU,MAAM,YAAY,KAAA;GAC5B,MAAK;GAEL,UAAA,oBAAC,QAAD;IACE,WAAU;IACV,cAAY,UAAU,YAAY;GACnC,CAAA;EACK,CAAA,CACR,EAAA,CAAA;CAEU,CAAA;AAEpB"}
|
package/dist/form/index.d.ts
CHANGED
package/dist/form/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { FormValuesProvider } from "./hooks/values.js";
|
|
2
|
+
import { FormFieldFrame } from "./components/base/field.js";
|
|
2
3
|
import { BuilderComponent } from "./components/fields/builder.js";
|
|
3
4
|
import { CheckboxComponent } from "./components/fields/checkbox.js";
|
|
4
5
|
import { ChoiceComponent } from "./components/fields/choice.js";
|
|
@@ -19,4 +20,4 @@ import { TimeInputComponent } from "./components/fields/time-input.js";
|
|
|
19
20
|
import { ToggleComponent } from "./components/fields/toggle.js";
|
|
20
21
|
import { WizardComponent, WizardStepComponent } from "./components/wizard.js";
|
|
21
22
|
import { formComponents } from "./plugin.js";
|
|
22
|
-
export { BuilderComponent, CheckboxComponent, ChoiceComponent, ColorPickerFieldComponent, DateInputComponent, DateTimeInputComponent, FileUploadComponent, FormComponent, FormValuesProvider, HiddenInputComponent, NumberInputComponent, OtpInputComponent, PasswordInputComponent, RepeaterComponent, SelectComponent, TextInputComponent, TextareaComponent, TimeInputComponent, ToggleComponent, WizardComponent, WizardStepComponent, formComponents };
|
|
23
|
+
export { BuilderComponent, CheckboxComponent, ChoiceComponent, ColorPickerFieldComponent, DateInputComponent, DateTimeInputComponent, FileUploadComponent, FormComponent, FormFieldFrame, FormValuesProvider, HiddenInputComponent, NumberInputComponent, OtpInputComponent, PasswordInputComponent, RepeaterComponent, SelectComponent, TextInputComponent, TextareaComponent, TimeInputComponent, ToggleComponent, WizardComponent, WizardStepComponent, formComponents };
|
package/dist/form/toolkit.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Entry point for building custom form fields outside the package. Form
|
|
3
3
|
* modules not re-exported here are internal and may change without notice.
|
|
4
4
|
*/
|
|
5
|
-
export { FormFieldFrame } from './components/base/field.js';
|
|
5
|
+
export { FormFieldFrame, type FormFieldControlProps } from './components/base/field.js';
|
|
6
6
|
export { useFormContext } from './hooks/context.js';
|
|
7
7
|
export { FieldScopeProvider, useFieldScope } from './hooks/field-scope.js';
|
|
8
8
|
export { fieldProps, walkFields } from './lib/field-props.js';
|
package/dist/lattice.css
CHANGED
|
@@ -97,6 +97,9 @@
|
|
|
97
97
|
--lt-control-h-md: 2.25rem;
|
|
98
98
|
--lt-control-h-lg: 2.5rem;
|
|
99
99
|
|
|
100
|
+
/* >= 1rem, or iOS Safari auto-zooms the page on focus */
|
|
101
|
+
--lt-input-font-size-mobile: 1rem;
|
|
102
|
+
|
|
100
103
|
/* Table cell padding — table density lever */
|
|
101
104
|
--lt-table-cell-x: calc(var(--spacing) * 4);
|
|
102
105
|
--lt-table-cell-y: calc(var(--spacing) * 4);
|
|
@@ -588,6 +591,19 @@
|
|
|
588
591
|
}
|
|
589
592
|
}
|
|
590
593
|
|
|
594
|
+
/* iOS Safari auto-zooms when a focused control computes below 16px; unlayered
|
|
595
|
+
so it beats the text-size utilities on the components. */
|
|
596
|
+
@media (width < theme(--breakpoint-md)) {
|
|
597
|
+
[data-slot="input"],
|
|
598
|
+
[data-slot="textarea"],
|
|
599
|
+
[data-slot="native-select"],
|
|
600
|
+
[data-slot="combobox-search"],
|
|
601
|
+
[data-slot="prompt-input"],
|
|
602
|
+
.lattice-prose[contenteditable="true"] {
|
|
603
|
+
font-size: var(--lt-input-font-size-mobile);
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
|
|
591
607
|
.lt-badge {
|
|
592
608
|
display: inline-flex;
|
|
593
609
|
align-items: center;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useT } from "../../i18n/instance.js";
|
|
2
2
|
import { Popover, PopoverContent, PopoverTrigger } from "../../ui/popover.js";
|
|
3
|
-
import { Checkbox } from "../../ui/checkbox.js";
|
|
4
3
|
import { IconButton } from "../../ui/icon-button.js";
|
|
4
|
+
import { Checkbox } from "../../ui/checkbox.js";
|
|
5
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
6
|
//#region resources/js/table/components/column-visibility-menu.tsx
|
|
7
7
|
function ColumnVisibilityMenu({ columns, hasHidden, isVisible, onReset, onToggle, processing, visibleColumnCount }) {
|
|
@@ -8,8 +8,8 @@ import { ResolvedNodesProvider } from "../../form/hooks/resolved-nodes.js";
|
|
|
8
8
|
import { FormValuesProvider, useFormValues, useSetFormValue } from "../../form/hooks/values.js";
|
|
9
9
|
import { FieldCommitOverrideProvider } from "../../form/hooks/use-field-commit.js";
|
|
10
10
|
import { TableCellProvider } from "../../form/hooks/row-layout-context.js";
|
|
11
|
-
import { Checkbox } from "../../ui/checkbox.js";
|
|
12
11
|
import { IconButton } from "../../ui/icon-button.js";
|
|
12
|
+
import { Checkbox } from "../../ui/checkbox.js";
|
|
13
13
|
import { filterValue, isActiveFilterValue } from "../lib/filter-values.js";
|
|
14
14
|
import { isTruthy } from "../../lib/is-truthy.js";
|
|
15
15
|
import { useCallback, useMemo, useRef } from "react";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { useT } from "../../i18n/instance.js";
|
|
2
2
|
import { cn } from "../../lib/utils.js";
|
|
3
3
|
import { Icon } from "../../icons/sprite.js";
|
|
4
|
-
import { Input } from "../../ui/input.js";
|
|
5
4
|
import { IconButton } from "../../ui/icon-button.js";
|
|
5
|
+
import { Input } from "../../ui/input.js";
|
|
6
6
|
import { NativeSelect } from "../../ui/native-select.js";
|
|
7
7
|
import { useEffect, useState } from "react";
|
|
8
8
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -2,8 +2,8 @@ import { useT } from "../../i18n/instance.js";
|
|
|
2
2
|
import { cn } from "../../lib/utils.js";
|
|
3
3
|
import { Icon } from "../../icons/sprite.js";
|
|
4
4
|
import { useDebouncedCallback } from "../../lib/use-debounced-callback.js";
|
|
5
|
-
import { Input } from "../../ui/input.js";
|
|
6
5
|
import { IconButton } from "../../ui/icon-button.js";
|
|
6
|
+
import { Input } from "../../ui/input.js";
|
|
7
7
|
import { useEffect, useRef, useState } from "react";
|
|
8
8
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
9
|
//#region resources/js/table/components/table-search.tsx
|
|
@@ -322,6 +322,13 @@ export type Choice = {
|
|
|
322
322
|
export type CloseModal = {
|
|
323
323
|
readonly modal: string | null;
|
|
324
324
|
};
|
|
325
|
+
export type CodeBlock = {
|
|
326
|
+
code: string;
|
|
327
|
+
copyable: boolean;
|
|
328
|
+
language: CodeBlockLanguage;
|
|
329
|
+
wrap: boolean;
|
|
330
|
+
};
|
|
331
|
+
export type CodeBlockLanguage = "text" | "json" | "javascript" | "shell" | "php";
|
|
325
332
|
export type Collapsible = {
|
|
326
333
|
collapsed: boolean;
|
|
327
334
|
rememberState: boolean;
|
|
@@ -409,6 +416,7 @@ export type ComponentPropsMap = {
|
|
|
409
416
|
"chat.box": ChatBox;
|
|
410
417
|
"chat.part.text": TextPart;
|
|
411
418
|
"chat.part.tool-call": ToolCallPart;
|
|
419
|
+
"code-block": CodeBlock;
|
|
412
420
|
collapsible: Collapsible;
|
|
413
421
|
dropdown: Dropdown;
|
|
414
422
|
"field.builder": Builder;
|
|
@@ -841,7 +849,7 @@ export type MoneyColumn = {
|
|
|
841
849
|
toggleable: boolean;
|
|
842
850
|
width: ColumnWidth;
|
|
843
851
|
};
|
|
844
|
-
export type NodeType = "action" | "action.bulk" | "action.group" | "avatar" | "badge" | "breadcrumbs" | "button" | "callouts" | "card" | "chart" | "chat.box" | "chat.part.text" | "chat.part.tool-call" | "collapsible" | "dropdown" | "field.builder" | "field.checkbox" | "field.choice" | "field.color-picker" | "field.date-input" | "field.date-time-input" | "field.file-upload" | "field.hidden-input" | "field.number-input" | "field.otp" | "field.password-input" | "field.repeater" | "field.rich-editor" | "field.select" | "field.text-input" | "field.textarea" | "field.time-input" | "field.toggle" | "floating-panel" | "form" | "fragment" | "grid" | "heading" | "icon" | "image" | "link" | "menu" | "menu-item" | "modal" | "notifications" | "outlet" | "progress" | "raw-block" | "remote.data-list" | "section" | "segmented-control" | "separator" | "sidebar" | "stack" | "tab" | "table" | "tabs" | "text" | "tooltip" | "topbar" | "wizard" | "wizard-step";
|
|
852
|
+
export type NodeType = "action" | "action.bulk" | "action.group" | "avatar" | "badge" | "breadcrumbs" | "button" | "callouts" | "card" | "chart" | "chat.box" | "chat.part.text" | "chat.part.tool-call" | "code-block" | "collapsible" | "dropdown" | "field.builder" | "field.checkbox" | "field.choice" | "field.color-picker" | "field.date-input" | "field.date-time-input" | "field.file-upload" | "field.hidden-input" | "field.number-input" | "field.otp" | "field.password-input" | "field.repeater" | "field.rich-editor" | "field.select" | "field.text-input" | "field.textarea" | "field.time-input" | "field.toggle" | "floating-panel" | "form" | "fragment" | "grid" | "heading" | "icon" | "image" | "link" | "menu" | "menu-item" | "modal" | "notifications" | "outlet" | "progress" | "raw-block" | "remote.data-list" | "section" | "segmented-control" | "separator" | "sidebar" | "stack" | "tab" | "table" | "tabs" | "text" | "tooltip" | "topbar" | "wizard" | "wizard-step";
|
|
845
853
|
export type NotificationItem = {
|
|
846
854
|
readonly actions: Node[];
|
|
847
855
|
readonly body: Translatable | string | null;
|
|
@@ -1390,7 +1398,7 @@ export type Translatable = {
|
|
|
1390
1398
|
payload: Record<string, string>;
|
|
1391
1399
|
replacements: Record<string, string | number | boolean>;
|
|
1392
1400
|
};
|
|
1393
|
-
export type UiNodeType = "avatar" | "badge" | "button" | "card" | "chart" | "collapsible" | "floating-panel" | "grid" | "heading" | "icon" | "image" | "link" | "modal" | "progress" | "raw-block" | "section" | "segmented-control" | "separator" | "stack" | "tab" | "tabs" | "text" | "tooltip";
|
|
1401
|
+
export type UiNodeType = "avatar" | "badge" | "button" | "card" | "chart" | "code-block" | "collapsible" | "floating-panel" | "grid" | "heading" | "icon" | "image" | "link" | "modal" | "progress" | "raw-block" | "section" | "segmented-control" | "separator" | "stack" | "tab" | "tabs" | "text" | "tooltip";
|
|
1394
1402
|
export type UnreadCount = {
|
|
1395
1403
|
readonly unreadCount: number;
|
|
1396
1404
|
};
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { useEffect, useRef } from "react";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { javascript } from "@codemirror/lang-javascript";
|
|
4
|
+
import { json } from "@codemirror/lang-json";
|
|
5
|
+
import { php } from "@codemirror/lang-php";
|
|
6
|
+
import { HighlightStyle, StreamLanguage, syntaxHighlighting } from "@codemirror/language";
|
|
7
|
+
import { shell } from "@codemirror/legacy-modes/mode/shell";
|
|
8
|
+
import { Compartment, EditorState } from "@codemirror/state";
|
|
9
|
+
import { EditorView } from "@codemirror/view";
|
|
10
|
+
import { tags } from "@lezer/highlight";
|
|
11
|
+
//#region resources/js/ui/code-block-view.tsx
|
|
12
|
+
var languages = {
|
|
13
|
+
text: [],
|
|
14
|
+
json: json(),
|
|
15
|
+
javascript: javascript(),
|
|
16
|
+
shell: StreamLanguage.define(shell),
|
|
17
|
+
php: php()
|
|
18
|
+
};
|
|
19
|
+
var highlightStyle = HighlightStyle.define([
|
|
20
|
+
{
|
|
21
|
+
tag: tags.comment,
|
|
22
|
+
color: "var(--lt-muted-fg)",
|
|
23
|
+
fontStyle: "italic"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
tag: [
|
|
27
|
+
tags.keyword,
|
|
28
|
+
tags.operatorKeyword,
|
|
29
|
+
tags.controlKeyword
|
|
30
|
+
],
|
|
31
|
+
color: "var(--lt-primary)"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
tag: [tags.string, tags.special(tags.string)],
|
|
35
|
+
color: "var(--lt-success)"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
tag: [
|
|
39
|
+
tags.number,
|
|
40
|
+
tags.bool,
|
|
41
|
+
tags.null
|
|
42
|
+
],
|
|
43
|
+
color: "var(--lt-info)"
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
tag: [tags.function(tags.variableName), tags.labelName],
|
|
47
|
+
color: "var(--lt-accent-fg)"
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
tag: [tags.typeName, tags.className],
|
|
51
|
+
color: "var(--lt-danger)"
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
tag: tags.meta,
|
|
55
|
+
color: "var(--lt-muted-fg)"
|
|
56
|
+
}
|
|
57
|
+
]);
|
|
58
|
+
var codeBlockTheme = EditorView.theme({
|
|
59
|
+
"&": {
|
|
60
|
+
backgroundColor: "transparent",
|
|
61
|
+
color: "var(--lt-fg)",
|
|
62
|
+
fontSize: "0.75rem"
|
|
63
|
+
},
|
|
64
|
+
".cm-scroller": {
|
|
65
|
+
fontFamily: "var(--lt-font-mono)",
|
|
66
|
+
lineHeight: "1.5",
|
|
67
|
+
overflow: "auto"
|
|
68
|
+
},
|
|
69
|
+
".cm-content": { padding: "0.75rem" },
|
|
70
|
+
".cm-line": { padding: "0" }
|
|
71
|
+
});
|
|
72
|
+
var copyableTheme = EditorView.theme({ ".cm-content": { padding: "2.75rem 0.75rem 0.75rem" } });
|
|
73
|
+
function CodeBlockView({ children, copyable, language, wrap }) {
|
|
74
|
+
const container = useRef(null);
|
|
75
|
+
useEffect(() => {
|
|
76
|
+
if (!container.current) return;
|
|
77
|
+
const languageCompartment = new Compartment();
|
|
78
|
+
const customLanguage = typeof language === "function" ? language : null;
|
|
79
|
+
const initialLanguage = typeof language === "function" ? [] : languages[language];
|
|
80
|
+
const view = new EditorView({
|
|
81
|
+
doc: children,
|
|
82
|
+
parent: container.current,
|
|
83
|
+
extensions: [
|
|
84
|
+
EditorState.readOnly.of(true),
|
|
85
|
+
EditorView.editable.of(false),
|
|
86
|
+
EditorView.contentAttributes.of({ role: "code" }),
|
|
87
|
+
languageCompartment.of(initialLanguage),
|
|
88
|
+
syntaxHighlighting(highlightStyle),
|
|
89
|
+
codeBlockTheme,
|
|
90
|
+
copyable ? copyableTheme : [],
|
|
91
|
+
wrap ? EditorView.lineWrapping : []
|
|
92
|
+
]
|
|
93
|
+
});
|
|
94
|
+
let active = true;
|
|
95
|
+
if (customLanguage) customLanguage().then((extension) => {
|
|
96
|
+
if (active) view.dispatch({ effects: languageCompartment.reconfigure(extension) });
|
|
97
|
+
}).catch((error) => {
|
|
98
|
+
if (active) console.warn("[lattice] CodeBlock language failed to load.", error);
|
|
99
|
+
});
|
|
100
|
+
return () => {
|
|
101
|
+
active = false;
|
|
102
|
+
view.destroy();
|
|
103
|
+
};
|
|
104
|
+
}, [
|
|
105
|
+
children,
|
|
106
|
+
copyable,
|
|
107
|
+
language,
|
|
108
|
+
wrap
|
|
109
|
+
]);
|
|
110
|
+
return /* @__PURE__ */ jsx("div", { ref: container });
|
|
111
|
+
}
|
|
112
|
+
//#endregion
|
|
113
|
+
export { CodeBlockView as default };
|
|
114
|
+
|
|
115
|
+
//# sourceMappingURL=code-block-view.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code-block-view.js","names":[],"sources":["../../resources/js/ui/code-block-view.tsx"],"sourcesContent":["import { useEffect, useRef } from \"react\";\nimport { javascript } from \"@codemirror/lang-javascript\";\nimport { json } from \"@codemirror/lang-json\";\nimport { php } from \"@codemirror/lang-php\";\nimport { HighlightStyle, StreamLanguage, syntaxHighlighting } from \"@codemirror/language\";\nimport { shell } from \"@codemirror/legacy-modes/mode/shell\";\nimport { Compartment, EditorState, type Extension } from \"@codemirror/state\";\nimport { EditorView } from \"@codemirror/view\";\nimport { tags } from \"@lezer/highlight\";\nimport type { CodeBlockLanguage, CodeBlockViewProps } from \"./code-block\";\n\nconst languages: Record<CodeBlockLanguage, Extension> = {\n text: [],\n json: json(),\n javascript: javascript(),\n shell: StreamLanguage.define(shell),\n php: php(),\n};\n\nconst highlightStyle = HighlightStyle.define([\n { tag: tags.comment, color: \"var(--lt-muted-fg)\", fontStyle: \"italic\" },\n { tag: [tags.keyword, tags.operatorKeyword, tags.controlKeyword], color: \"var(--lt-primary)\" },\n { tag: [tags.string, tags.special(tags.string)], color: \"var(--lt-success)\" },\n { tag: [tags.number, tags.bool, tags.null], color: \"var(--lt-info)\" },\n { tag: [tags.function(tags.variableName), tags.labelName], color: \"var(--lt-accent-fg)\" },\n { tag: [tags.typeName, tags.className], color: \"var(--lt-danger)\" },\n { tag: tags.meta, color: \"var(--lt-muted-fg)\" },\n]);\n\nconst codeBlockTheme = EditorView.theme({\n \"&\": {\n backgroundColor: \"transparent\",\n color: \"var(--lt-fg)\",\n fontSize: \"0.75rem\",\n },\n \".cm-scroller\": {\n fontFamily: \"var(--lt-font-mono)\",\n lineHeight: \"1.5\",\n overflow: \"auto\",\n },\n \".cm-content\": { padding: \"0.75rem\" },\n \".cm-line\": { padding: \"0\" },\n});\n\nconst copyableTheme = EditorView.theme({\n \".cm-content\": { padding: \"2.75rem 0.75rem 0.75rem\" },\n});\n\nfunction CodeBlockView({ children, copyable, language, wrap }: CodeBlockViewProps) {\n const container = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!container.current) {\n return;\n }\n\n const languageCompartment = new Compartment();\n const customLanguage = typeof language === \"function\" ? language : null;\n const initialLanguage = typeof language === \"function\" ? [] : languages[language];\n const view = new EditorView({\n doc: children,\n parent: container.current,\n extensions: [\n EditorState.readOnly.of(true),\n EditorView.editable.of(false),\n EditorView.contentAttributes.of({ role: \"code\" }),\n languageCompartment.of(initialLanguage),\n syntaxHighlighting(highlightStyle),\n codeBlockTheme,\n copyable ? copyableTheme : [],\n wrap ? EditorView.lineWrapping : [],\n ],\n });\n let active = true;\n\n if (customLanguage) {\n void customLanguage()\n .then((extension) => {\n if (active) {\n view.dispatch({ effects: languageCompartment.reconfigure(extension) });\n }\n })\n .catch((error: unknown) => {\n if (active) {\n console.warn(\"[lattice] CodeBlock language failed to load.\", error);\n }\n });\n }\n\n return () => {\n active = false;\n view.destroy();\n };\n }, [children, copyable, language, wrap]);\n\n return <div ref={container} />;\n}\n\nexport default CodeBlockView;\n"],"mappings":";;;;;;;;;;;AAWA,IAAM,YAAkD;CACtD,MAAM,CAAC;CACP,MAAM,KAAK;CACX,YAAY,WAAW;CACvB,OAAO,eAAe,OAAO,KAAK;CAClC,KAAK,IAAI;AACX;AAEA,IAAM,iBAAiB,eAAe,OAAO;CAC3C;EAAE,KAAK,KAAK;EAAS,OAAO;EAAsB,WAAW;CAAS;CACtE;EAAE,KAAK;GAAC,KAAK;GAAS,KAAK;GAAiB,KAAK;EAAc;EAAG,OAAO;CAAoB;CAC7F;EAAE,KAAK,CAAC,KAAK,QAAQ,KAAK,QAAQ,KAAK,MAAM,CAAC;EAAG,OAAO;CAAoB;CAC5E;EAAE,KAAK;GAAC,KAAK;GAAQ,KAAK;GAAM,KAAK;EAAI;EAAG,OAAO;CAAiB;CACpE;EAAE,KAAK,CAAC,KAAK,SAAS,KAAK,YAAY,GAAG,KAAK,SAAS;EAAG,OAAO;CAAsB;CACxF;EAAE,KAAK,CAAC,KAAK,UAAU,KAAK,SAAS;EAAG,OAAO;CAAmB;CAClE;EAAE,KAAK,KAAK;EAAM,OAAO;CAAqB;AAChD,CAAC;AAED,IAAM,iBAAiB,WAAW,MAAM;CACtC,KAAK;EACH,iBAAiB;EACjB,OAAO;EACP,UAAU;CACZ;CACA,gBAAgB;EACd,YAAY;EACZ,YAAY;EACZ,UAAU;CACZ;CACA,eAAe,EAAE,SAAS,UAAU;CACpC,YAAY,EAAE,SAAS,IAAI;AAC7B,CAAC;AAED,IAAM,gBAAgB,WAAW,MAAM,EACrC,eAAe,EAAE,SAAS,0BAA0B,EACtD,CAAC;AAED,SAAS,cAAc,EAAE,UAAU,UAAU,UAAU,QAA4B;CACjF,MAAM,YAAY,OAAuB,IAAI;CAE7C,gBAAgB;EACd,IAAI,CAAC,UAAU,SACb;EAGF,MAAM,sBAAsB,IAAI,YAAY;EAC5C,MAAM,iBAAiB,OAAO,aAAa,aAAa,WAAW;EACnE,MAAM,kBAAkB,OAAO,aAAa,aAAa,CAAC,IAAI,UAAU;EACxE,MAAM,OAAO,IAAI,WAAW;GAC1B,KAAK;GACL,QAAQ,UAAU;GAClB,YAAY;IACV,YAAY,SAAS,GAAG,IAAI;IAC5B,WAAW,SAAS,GAAG,KAAK;IAC5B,WAAW,kBAAkB,GAAG,EAAE,MAAM,OAAO,CAAC;IAChD,oBAAoB,GAAG,eAAe;IACtC,mBAAmB,cAAc;IACjC;IACA,WAAW,gBAAgB,CAAC;IAC5B,OAAO,WAAW,eAAe,CAAC;GACpC;EACF,CAAC;EACD,IAAI,SAAS;EAEb,IAAI,gBACF,eAAoB,CAAC,CAClB,MAAM,cAAc;GACnB,IAAI,QACF,KAAK,SAAS,EAAE,SAAS,oBAAoB,YAAY,SAAS,EAAE,CAAC;EAEzE,CAAC,CAAC,CACD,OAAO,UAAmB;GACzB,IAAI,QACF,QAAQ,KAAK,gDAAgD,KAAK;EAEtE,CAAC;EAGL,aAAa;GACX,SAAS;GACT,KAAK,QAAQ;EACf;CACF,GAAG;EAAC;EAAU;EAAU;EAAU;CAAI,CAAC;CAEvC,OAAO,oBAAC,OAAD,EAAK,KAAK,UAAY,CAAA;AAC/B"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { ComponentProps } from 'react';
|
|
2
|
+
import { Extension } from '@codemirror/state';
|
|
3
|
+
import { RendererComponent } from '../core/types.js';
|
|
4
|
+
type CodeBlockLanguage = "text" | "json" | "javascript" | "shell" | "php";
|
|
5
|
+
type CodeBlockLanguageLoader = () => Promise<Extension>;
|
|
6
|
+
interface CodeBlockProps extends Omit<ComponentProps<"div">, "children"> {
|
|
7
|
+
children: string;
|
|
8
|
+
copyable?: boolean;
|
|
9
|
+
language?: CodeBlockLanguage | CodeBlockLanguageLoader;
|
|
10
|
+
wrap?: boolean;
|
|
11
|
+
}
|
|
12
|
+
interface CodeBlockViewProps {
|
|
13
|
+
children: string;
|
|
14
|
+
copyable: boolean;
|
|
15
|
+
language: CodeBlockLanguage | CodeBlockLanguageLoader;
|
|
16
|
+
wrap: boolean;
|
|
17
|
+
}
|
|
18
|
+
declare function CodeBlock({ "aria-label": ariaLabel, children, className, copyable, language, role, wrap, ...props }: CodeBlockProps): import("react").JSX.Element;
|
|
19
|
+
declare const CodeBlockComponent: RendererComponent<"code-block">;
|
|
20
|
+
export default CodeBlockComponent;
|
|
21
|
+
export { CodeBlock };
|
|
22
|
+
export type { CodeBlockLanguage, CodeBlockLanguageLoader, CodeBlockProps, CodeBlockViewProps };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { cn } from "../lib/utils.js";
|
|
2
|
+
import { CopyButton } from "./copyable-text.js";
|
|
3
|
+
import { Suspense, lazy } from "react";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
//#region resources/js/ui/code-block.tsx
|
|
6
|
+
var CodeBlockView = lazy(() => import("./code-block-view.js"));
|
|
7
|
+
function CodeBlock({ "aria-label": ariaLabel, children, className, copyable = false, language = "text", role = ariaLabel ? "region" : void 0, wrap = false, ...props }) {
|
|
8
|
+
const fallback = /* @__PURE__ */ jsx("pre", {
|
|
9
|
+
className: cn("max-w-full overflow-x-auto p-3 font-lt-mono text-xs", wrap && "whitespace-pre-wrap wrap-anywhere", copyable && "pt-11"),
|
|
10
|
+
children
|
|
11
|
+
});
|
|
12
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
13
|
+
"data-slot": "code-block",
|
|
14
|
+
"aria-label": ariaLabel,
|
|
15
|
+
role,
|
|
16
|
+
...props,
|
|
17
|
+
className: cn("relative max-w-full overflow-hidden rounded-lt-sm bg-lt-muted text-lt-fg", className),
|
|
18
|
+
children: [copyable ? /* @__PURE__ */ jsx(CopyButton, {
|
|
19
|
+
value: children,
|
|
20
|
+
label: ariaLabel ?? "code",
|
|
21
|
+
iconOnly: true,
|
|
22
|
+
className: "absolute top-2 right-2 z-10 bg-lt-bg/80 hover:bg-lt-bg"
|
|
23
|
+
}) : null, /* @__PURE__ */ jsx(Suspense, {
|
|
24
|
+
fallback,
|
|
25
|
+
children: /* @__PURE__ */ jsx(CodeBlockView, {
|
|
26
|
+
copyable,
|
|
27
|
+
language,
|
|
28
|
+
wrap,
|
|
29
|
+
children
|
|
30
|
+
})
|
|
31
|
+
})]
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
var CodeBlockComponent = ({ node }) => /* @__PURE__ */ jsx(CodeBlock, {
|
|
35
|
+
copyable: node.props.copyable,
|
|
36
|
+
language: node.props.language,
|
|
37
|
+
wrap: node.props.wrap,
|
|
38
|
+
children: node.props.code
|
|
39
|
+
});
|
|
40
|
+
//#endregion
|
|
41
|
+
export { CodeBlock, CodeBlockComponent as default };
|
|
42
|
+
|
|
43
|
+
//# sourceMappingURL=code-block.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code-block.js","names":[],"sources":["../../resources/js/ui/code-block.tsx"],"sourcesContent":["import { lazy, Suspense } from \"react\";\nimport type { ComponentProps } from \"react\";\nimport type { Extension } from \"@codemirror/state\";\nimport type { RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { CopyButton } from \"./copyable-text\";\n\nconst CodeBlockView = lazy(() => import(\"./code-block-view\"));\n\ntype CodeBlockLanguage = \"text\" | \"json\" | \"javascript\" | \"shell\" | \"php\";\ntype CodeBlockLanguageLoader = () => Promise<Extension>;\n\ninterface CodeBlockProps extends Omit<ComponentProps<\"div\">, \"children\"> {\n children: string;\n copyable?: boolean;\n language?: CodeBlockLanguage | CodeBlockLanguageLoader;\n wrap?: boolean;\n}\n\ninterface CodeBlockViewProps {\n children: string;\n copyable: boolean;\n language: CodeBlockLanguage | CodeBlockLanguageLoader;\n wrap: boolean;\n}\n\nfunction CodeBlock({\n \"aria-label\": ariaLabel,\n children,\n className,\n copyable = false,\n language = \"text\",\n role = ariaLabel ? \"region\" : undefined,\n wrap = false,\n ...props\n}: CodeBlockProps) {\n const fallback = (\n <pre\n className={cn(\n \"max-w-full overflow-x-auto p-3 font-lt-mono text-xs\",\n wrap && \"whitespace-pre-wrap wrap-anywhere\",\n copyable && \"pt-11\",\n )}\n >\n {children}\n </pre>\n );\n\n return (\n <div\n data-slot=\"code-block\"\n aria-label={ariaLabel}\n role={role}\n {...props}\n className={cn(\n \"relative max-w-full overflow-hidden rounded-lt-sm bg-lt-muted text-lt-fg\",\n className,\n )}\n >\n {copyable ? (\n <CopyButton\n value={children}\n label={ariaLabel ?? \"code\"}\n iconOnly\n className=\"absolute top-2 right-2 z-10 bg-lt-bg/80 hover:bg-lt-bg\"\n />\n ) : null}\n <Suspense fallback={fallback}>\n <CodeBlockView copyable={copyable} language={language} wrap={wrap}>\n {children}\n </CodeBlockView>\n </Suspense>\n </div>\n );\n}\n\nconst CodeBlockComponent: RendererComponent<\"code-block\"> = ({ node }) => (\n <CodeBlock copyable={node.props.copyable} language={node.props.language} wrap={node.props.wrap}>\n {node.props.code}\n </CodeBlock>\n);\n\nexport default CodeBlockComponent;\nexport { CodeBlock };\nexport type { CodeBlockLanguage, CodeBlockLanguageLoader, CodeBlockProps, CodeBlockViewProps };\n"],"mappings":";;;;;AAOA,IAAM,gBAAgB,WAAW,OAAO,uBAAoB;AAmB5D,SAAS,UAAU,EACjB,cAAc,WACd,UACA,WACA,WAAW,OACX,WAAW,QACX,OAAO,YAAY,WAAW,KAAA,GAC9B,OAAO,OACP,GAAG,SACc;CACjB,MAAM,WACJ,oBAAC,OAAD;EACE,WAAW,GACT,uDACA,QAAQ,qCACR,YAAY,OACd;EAEC;CACE,CAAA;CAGP,OACE,qBAAC,OAAD;EACE,aAAU;EACV,cAAY;EACN;EACN,GAAI;EACJ,WAAW,GACT,4EACA,SACF;EARF,UAAA,CAUG,WACC,oBAAC,YAAD;GACE,OAAO;GACP,OAAO,aAAa;GACpB,UAAA;GACA,WAAU;EACX,CAAA,IACC,MACJ,oBAAC,UAAD;GAAoB;GAClB,UAAA,oBAAC,eAAD;IAAyB;IAAoB;IAAgB;IAC1D;GACY,CAAA;EACP,CAAA,CACP;;AAET;AAEA,IAAM,sBAAuD,EAAE,WAC7D,oBAAC,WAAD;CAAW,UAAU,KAAK,MAAM;CAAU,UAAU,KAAK,MAAM;CAAU,MAAM,KAAK,MAAM;CACvF,UAAA,KAAK,MAAM;AACH,CAAA"}
|
|
@@ -5,8 +5,10 @@ interface CopyButtonProps {
|
|
|
5
5
|
label: string;
|
|
6
6
|
testId?: string;
|
|
7
7
|
className?: string;
|
|
8
|
+
iconOnly?: boolean;
|
|
9
|
+
children?: ReactNode;
|
|
8
10
|
}
|
|
9
|
-
export declare function CopyButton({ value, label, testId, className }: CopyButtonProps): ReactNode;
|
|
11
|
+
export declare function CopyButton({ value, label, testId, className, iconOnly, children, }: CopyButtonProps): ReactNode;
|
|
10
12
|
interface CopyableTextProps {
|
|
11
13
|
value: string;
|
|
12
14
|
label: string;
|
package/dist/ui/copyable-text.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useT } from "../i18n/instance.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { Button } from "./button.js";
|
|
3
|
+
import { IconButton } from "./icon-button.js";
|
|
4
4
|
import { useEffect, useState } from "react";
|
|
5
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
6
|
//#region resources/js/ui/copyable-text.tsx
|
|
@@ -13,7 +13,7 @@ async function copyToClipboard(text) {
|
|
|
13
13
|
return false;
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
|
-
function CopyButton({ value, label, testId, className }) {
|
|
16
|
+
function CopyButton({ value, label, testId, className, iconOnly = false, children }) {
|
|
17
17
|
const { t } = useT("lattice");
|
|
18
18
|
const [copied, setCopied] = useState(false);
|
|
19
19
|
useEffect(() => {
|
|
@@ -21,21 +21,27 @@ function CopyButton({ value, label, testId, className }) {
|
|
|
21
21
|
const timeout = window.setTimeout(() => setCopied(false), 1500);
|
|
22
22
|
return () => window.clearTimeout(timeout);
|
|
23
23
|
}, [copied]);
|
|
24
|
-
function handleCopy() {
|
|
25
|
-
copyToClipboard(value);
|
|
26
|
-
setCopied(true);
|
|
24
|
+
async function handleCopy() {
|
|
25
|
+
if (await copyToClipboard(value)) setCopied(true);
|
|
27
26
|
}
|
|
28
27
|
const ariaLabel = copied ? t("common.copied-value", "Copied {{label}}", { label }) : t("common.copy-value", "Copy {{label}}", { label });
|
|
29
|
-
return /* @__PURE__ */
|
|
28
|
+
if (iconOnly) return /* @__PURE__ */ jsx(IconButton, {
|
|
29
|
+
icon: copied ? "check" : "copy",
|
|
30
|
+
label: ariaLabel,
|
|
31
|
+
"data-test": testId,
|
|
32
|
+
className,
|
|
33
|
+
onClick: () => void handleCopy()
|
|
34
|
+
});
|
|
35
|
+
return /* @__PURE__ */ jsx(Button, {
|
|
30
36
|
type: "button",
|
|
37
|
+
size: "sm",
|
|
38
|
+
emphasis: "outline",
|
|
39
|
+
icon: copied ? "check" : "copy",
|
|
31
40
|
"data-test": testId,
|
|
32
|
-
className
|
|
41
|
+
className,
|
|
33
42
|
"aria-label": ariaLabel,
|
|
34
|
-
onClick: handleCopy,
|
|
35
|
-
children:
|
|
36
|
-
name: copied ? "check" : "copy",
|
|
37
|
-
className: "size-lt-icon-xs"
|
|
38
|
-
}), copied ? t("common.copied", "Copied") : t("common.copy", "Copy")]
|
|
43
|
+
onClick: () => void handleCopy(),
|
|
44
|
+
children: copied ? t("common.copied", "Copied") : children ?? t("common.copy", "Copy")
|
|
39
45
|
});
|
|
40
46
|
}
|
|
41
47
|
function CopyableText({ value, label, testId, children }) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"copyable-text.js","names":[],"sources":["../../resources/js/ui/copyable-text.tsx"],"sourcesContent":["import { useT } from \"@lattice-php/lattice/i18n\";\nimport {
|
|
1
|
+
{"version":3,"file":"copyable-text.js","names":[],"sources":["../../resources/js/ui/copyable-text.tsx"],"sourcesContent":["import { useT } from \"@lattice-php/lattice/i18n\";\nimport { type ReactNode, useEffect, useState } from \"react\";\nimport { Button } from \"./button\";\nimport { IconButton } from \"./icon-button\";\n\nexport async function copyToClipboard(text: string): Promise<boolean> {\n if (!navigator?.clipboard) {\n return false;\n }\n\n try {\n await navigator.clipboard.writeText(text);\n\n return true;\n } catch {\n return false;\n }\n}\n\ninterface CopyButtonProps {\n value: string;\n label: string;\n testId?: string;\n className?: string;\n iconOnly?: boolean;\n children?: ReactNode;\n}\n\nexport function CopyButton({\n value,\n label,\n testId,\n className,\n iconOnly = false,\n children,\n}: CopyButtonProps): ReactNode {\n const { t } = useT(\"lattice\");\n const [copied, setCopied] = useState(false);\n\n useEffect(() => {\n if (!copied) {\n return;\n }\n\n const timeout = window.setTimeout(() => setCopied(false), 1500);\n\n return () => window.clearTimeout(timeout);\n }, [copied]);\n\n async function handleCopy(): Promise<void> {\n if (await copyToClipboard(value)) {\n setCopied(true);\n }\n }\n\n const ariaLabel = copied\n ? t(\"common.copied-value\", \"Copied {{label}}\", { label })\n : t(\"common.copy-value\", \"Copy {{label}}\", { label });\n\n if (iconOnly) {\n return (\n <IconButton\n icon={copied ? \"check\" : \"copy\"}\n label={ariaLabel}\n data-test={testId}\n className={className}\n onClick={() => void handleCopy()}\n />\n );\n }\n\n return (\n <Button\n type=\"button\"\n size=\"sm\"\n emphasis=\"outline\"\n icon={copied ? \"check\" : \"copy\"}\n data-test={testId}\n className={className}\n aria-label={ariaLabel}\n onClick={() => void handleCopy()}\n >\n {copied ? t(\"common.copied\", \"Copied\") : (children ?? t(\"common.copy\", \"Copy\"))}\n </Button>\n );\n}\n\ninterface CopyableTextProps {\n value: string;\n label: string;\n testId?: string;\n children?: ReactNode;\n}\n\nexport function CopyableText({ value, label, testId, children }: CopyableTextProps): ReactNode {\n return (\n <div className=\"inline-flex items-center gap-2\">\n {children ?? value}\n <CopyButton value={value} label={label} testId={testId} />\n </div>\n );\n}\n"],"mappings":";;;;;;AAKA,eAAsB,gBAAgB,MAAgC;CACpE,IAAI,CAAC,WAAW,WACd,OAAO;CAGT,IAAI;EACF,MAAM,UAAU,UAAU,UAAU,IAAI;EAExC,OAAO;CACT,QAAQ;EACN,OAAO;CACT;AACF;AAWA,SAAgB,WAAW,EACzB,OACA,OACA,QACA,WACA,WAAW,OACX,YAC6B;CAC7B,MAAM,EAAE,MAAM,KAAK,SAAS;CAC5B,MAAM,CAAC,QAAQ,aAAa,SAAS,KAAK;CAE1C,gBAAgB;EACd,IAAI,CAAC,QACH;EAGF,MAAM,UAAU,OAAO,iBAAiB,UAAU,KAAK,GAAG,IAAI;EAE9D,aAAa,OAAO,aAAa,OAAO;CAC1C,GAAG,CAAC,MAAM,CAAC;CAEX,eAAe,aAA4B;EACzC,IAAI,MAAM,gBAAgB,KAAK,GAC7B,UAAU,IAAI;CAElB;CAEA,MAAM,YAAY,SACd,EAAE,uBAAuB,oBAAoB,EAAE,MAAM,CAAC,IACtD,EAAE,qBAAqB,kBAAkB,EAAE,MAAM,CAAC;CAEtD,IAAI,UACF,OACE,oBAAC,YAAD;EACE,MAAM,SAAS,UAAU;EACzB,OAAO;EACP,aAAW;EACA;EACX,eAAe,KAAK,WAAW;CAChC,CAAA;CAIL,OACE,oBAAC,QAAD;EACE,MAAK;EACL,MAAK;EACL,UAAS;EACT,MAAM,SAAS,UAAU;EACzB,aAAW;EACA;EACX,cAAY;EACZ,eAAe,KAAK,WAAW;EAE9B,UAAA,SAAS,EAAE,iBAAiB,QAAQ,IAAK,YAAY,EAAE,eAAe,MAAM;CACvE,CAAA;AAEZ;AASA,SAAgB,aAAa,EAAE,OAAO,OAAO,QAAQ,YAA0C;CAC7F,OACE,qBAAC,OAAD;EAAK,WAAU;EAAf,UAAA,CACG,YAAY,OACb,oBAAC,YAAD;GAAmB;GAAc;GAAe;EAAS,CAAA,CACtD;;AAET"}
|
package/dist/ui/index.d.ts
CHANGED
|
@@ -5,6 +5,8 @@ export { Button, buttonVariants } from './button.js';
|
|
|
5
5
|
export type { Emphasis, Variant } from './button.js';
|
|
6
6
|
export { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from './card.js';
|
|
7
7
|
export { Checkbox } from './checkbox.js';
|
|
8
|
+
export { CodeBlock } from './code-block.js';
|
|
9
|
+
export type { CodeBlockLanguage, CodeBlockLanguageLoader, CodeBlockProps } from './code-block.js';
|
|
8
10
|
export { Combobox } from './combobox.js';
|
|
9
11
|
export { ConfirmDialog } from './confirm-dialog.js';
|
|
10
12
|
export { ActionTrigger, ActionTriggerProvider, useActionTrigger, useClickBehavior, } from './click-behavior.js';
|
|
@@ -18,6 +20,7 @@ export { Input } from './input.js';
|
|
|
18
20
|
export { default as InputError } from './input-error.js';
|
|
19
21
|
export { InputOTP } from './input-otp.js';
|
|
20
22
|
export { Label } from './label.js';
|
|
23
|
+
export { NativeSelect } from './native-select.js';
|
|
21
24
|
export { TextLink } from './link.js';
|
|
22
25
|
export { default as PasswordInput } from './password-input.js';
|
|
23
26
|
export { Popover, PopoverClose, PopoverContent, PopoverTrigger } from './popover.js';
|
package/dist/ui/index.js
CHANGED
|
@@ -11,6 +11,7 @@ import { Badge } from "./badge.js";
|
|
|
11
11
|
import { InfoTooltip } from "./info-tooltip.js";
|
|
12
12
|
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "./card.js";
|
|
13
13
|
import { CopyButton, CopyableText, copyToClipboard } from "./copyable-text.js";
|
|
14
|
+
import { CodeBlock } from "./code-block.js";
|
|
14
15
|
import { PreviewableImage } from "./image-preview.js";
|
|
15
16
|
import { TextLink } from "./link.js";
|
|
16
17
|
import { SegmentedPills } from "./segmented-pills.js";
|
|
@@ -24,4 +25,5 @@ import { InputOTP } from "./input-otp.js";
|
|
|
24
25
|
import PasswordInput from "./password-input.js";
|
|
25
26
|
import { Combobox } from "./combobox.js";
|
|
26
27
|
import { Textarea } from "./textarea.js";
|
|
27
|
-
|
|
28
|
+
import { NativeSelect } from "./native-select.js";
|
|
29
|
+
export { ActionMenuProvider, ActionTrigger, ActionTriggerProvider, AffixGroup, Badge, Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, CodeBlock, Combobox, ConfirmDialog, CopyButton, CopyableText, Dialog, DialogClose, DialogContent, DialogDescription, DialogHeader, DialogTitle, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, InfoTooltip, Input, InputError, InputOTP, Label, NativeSelect, PasswordInput, Popover, PopoverClose, PopoverContent, PopoverTrigger, PreviewableImage, SegmentedPills, Skeleton, Spinner, TextLink, Textarea, actionMenuItemClassName, buttonVariants, copyToClipboard, uiComponents, useActionMenu, useActionTrigger, useClickBehavior };
|
package/dist/ui/plugin.js
CHANGED
|
@@ -4,6 +4,7 @@ import AvatarComponent from "./avatar.js";
|
|
|
4
4
|
import BadgeComponent from "./badge.js";
|
|
5
5
|
import CardComponent from "./card.js";
|
|
6
6
|
import ChartComponent from "./chart.js";
|
|
7
|
+
import CodeBlockComponent from "./code-block.js";
|
|
7
8
|
import CollapsibleComponent from "./collapsible.js";
|
|
8
9
|
import FloatingPanelComponent from "./floating-panel.js";
|
|
9
10
|
import FragmentComponent from "./fragment.js";
|
|
@@ -30,6 +31,7 @@ var uiComponents = createPlugin({
|
|
|
30
31
|
button: eagerComponent(ButtonComponent),
|
|
31
32
|
card: eagerComponent(CardComponent),
|
|
32
33
|
chart: eagerComponent(ChartComponent),
|
|
34
|
+
"code-block": eagerComponent(CodeBlockComponent),
|
|
33
35
|
collapsible: eagerComponent(CollapsibleComponent),
|
|
34
36
|
"floating-panel": eagerComponent(FloatingPanelComponent),
|
|
35
37
|
fragment: eagerComponent(FragmentComponent),
|
package/dist/ui/plugin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","names":[],"sources":["../../resources/js/ui/plugin.ts"],"sourcesContent":["import {\n createPlugin,\n eagerComponent,\n type ComponentRegistryFor,\n} from \"@lattice-php/lattice/core/registry\";\nimport type { FragmentNodeType, UiNodeType } from \"@lattice-php/lattice/types/generated\";\nimport AvatarComponent from \"./avatar\";\nimport BadgeComponent from \"./badge\";\nimport ButtonComponent from \"./button\";\nimport CardComponent from \"./card\";\nimport ChartComponent from \"./chart\";\nimport CollapsibleComponent from \"./collapsible\";\nimport FloatingPanelComponent from \"./floating-panel\";\nimport FragmentComponent from \"./fragment\";\nimport GridComponent from \"./grid\";\nimport HeadingComponent from \"./heading\";\nimport IconComponent from \"./icon\";\nimport ImageComponent from \"./image\";\nimport LinkComponent from \"./link\";\nimport ModalComponent from \"./modal\";\nimport ProgressComponent from \"./progress\";\nimport RawBlockComponent from \"./raw-block\";\nimport SectionComponent from \"./section\";\nimport SegmentedControlComponent from \"./segmented-control\";\nimport SeparatorComponent from \"./separator\";\nimport StackComponent from \"./stack\";\nimport TabComponent, { TabsComponent } from \"./tabs\";\nimport TextComponent from \"./text\";\nimport TooltipComponent from \"./tooltip\";\n\ntype UiComponentType = UiNodeType | FragmentNodeType;\n\nexport const uiComponents = createPlugin({\n components: {\n avatar: eagerComponent(AvatarComponent),\n badge: eagerComponent(BadgeComponent),\n button: eagerComponent(ButtonComponent),\n card: eagerComponent(CardComponent),\n chart: eagerComponent(ChartComponent),\n collapsible: eagerComponent(CollapsibleComponent),\n \"floating-panel\": eagerComponent(FloatingPanelComponent),\n fragment: eagerComponent(FragmentComponent),\n grid: eagerComponent(GridComponent),\n heading: eagerComponent(HeadingComponent),\n icon: eagerComponent(IconComponent),\n image: eagerComponent(ImageComponent),\n link: eagerComponent(LinkComponent),\n modal: eagerComponent(ModalComponent),\n progress: eagerComponent(ProgressComponent),\n \"raw-block\": eagerComponent(RawBlockComponent),\n section: eagerComponent(SectionComponent),\n \"segmented-control\": eagerComponent(SegmentedControlComponent),\n separator: eagerComponent(SeparatorComponent),\n stack: eagerComponent(StackComponent),\n tab: eagerComponent(TabComponent),\n tabs: eagerComponent(TabsComponent),\n text: eagerComponent(TextComponent),\n tooltip: eagerComponent(TooltipComponent),\n } satisfies ComponentRegistryFor<UiComponentType>,\n name: \"lattice/ui\",\n});\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"plugin.js","names":[],"sources":["../../resources/js/ui/plugin.ts"],"sourcesContent":["import {\n createPlugin,\n eagerComponent,\n type ComponentRegistryFor,\n} from \"@lattice-php/lattice/core/registry\";\nimport type { FragmentNodeType, UiNodeType } from \"@lattice-php/lattice/types/generated\";\nimport AvatarComponent from \"./avatar\";\nimport BadgeComponent from \"./badge\";\nimport ButtonComponent from \"./button\";\nimport CardComponent from \"./card\";\nimport ChartComponent from \"./chart\";\nimport CodeBlockComponent from \"./code-block\";\nimport CollapsibleComponent from \"./collapsible\";\nimport FloatingPanelComponent from \"./floating-panel\";\nimport FragmentComponent from \"./fragment\";\nimport GridComponent from \"./grid\";\nimport HeadingComponent from \"./heading\";\nimport IconComponent from \"./icon\";\nimport ImageComponent from \"./image\";\nimport LinkComponent from \"./link\";\nimport ModalComponent from \"./modal\";\nimport ProgressComponent from \"./progress\";\nimport RawBlockComponent from \"./raw-block\";\nimport SectionComponent from \"./section\";\nimport SegmentedControlComponent from \"./segmented-control\";\nimport SeparatorComponent from \"./separator\";\nimport StackComponent from \"./stack\";\nimport TabComponent, { TabsComponent } from \"./tabs\";\nimport TextComponent from \"./text\";\nimport TooltipComponent from \"./tooltip\";\n\ntype UiComponentType = UiNodeType | FragmentNodeType;\n\nexport const uiComponents = createPlugin({\n components: {\n avatar: eagerComponent(AvatarComponent),\n badge: eagerComponent(BadgeComponent),\n button: eagerComponent(ButtonComponent),\n card: eagerComponent(CardComponent),\n chart: eagerComponent(ChartComponent),\n \"code-block\": eagerComponent(CodeBlockComponent),\n collapsible: eagerComponent(CollapsibleComponent),\n \"floating-panel\": eagerComponent(FloatingPanelComponent),\n fragment: eagerComponent(FragmentComponent),\n grid: eagerComponent(GridComponent),\n heading: eagerComponent(HeadingComponent),\n icon: eagerComponent(IconComponent),\n image: eagerComponent(ImageComponent),\n link: eagerComponent(LinkComponent),\n modal: eagerComponent(ModalComponent),\n progress: eagerComponent(ProgressComponent),\n \"raw-block\": eagerComponent(RawBlockComponent),\n section: eagerComponent(SectionComponent),\n \"segmented-control\": eagerComponent(SegmentedControlComponent),\n separator: eagerComponent(SeparatorComponent),\n stack: eagerComponent(StackComponent),\n tab: eagerComponent(TabComponent),\n tabs: eagerComponent(TabsComponent),\n text: eagerComponent(TextComponent),\n tooltip: eagerComponent(TooltipComponent),\n } satisfies ComponentRegistryFor<UiComponentType>,\n name: \"lattice/ui\",\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAiCA,IAAa,eAAe,aAAa;CACvC,YAAY;EACV,QAAQ,eAAe,eAAe;EACtC,OAAO,eAAe,cAAc;EACpC,QAAQ,eAAe,eAAe;EACtC,MAAM,eAAe,aAAa;EAClC,OAAO,eAAe,cAAc;EACpC,cAAc,eAAe,kBAAkB;EAC/C,aAAa,eAAe,oBAAoB;EAChD,kBAAkB,eAAe,sBAAsB;EACvD,UAAU,eAAe,iBAAiB;EAC1C,MAAM,eAAe,aAAa;EAClC,SAAS,eAAe,gBAAgB;EACxC,MAAM,eAAe,aAAa;EAClC,OAAO,eAAe,cAAc;EACpC,MAAM,eAAe,aAAa;EAClC,OAAO,eAAe,cAAc;EACpC,UAAU,eAAe,iBAAiB;EAC1C,aAAa,eAAe,iBAAiB;EAC7C,SAAS,eAAe,gBAAgB;EACxC,qBAAqB,eAAe,yBAAyB;EAC7D,WAAW,eAAe,kBAAkB;EAC5C,OAAO,eAAe,cAAc;EACpC,KAAK,eAAe,YAAY;EAChC,MAAM,eAAe,aAAa;EAClC,MAAM,eAAe,aAAa;EAClC,SAAS,eAAe,gBAAgB;CAC1C;CACA,MAAM;AACR,CAAC"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { ComponentProps } from 'react';
|
|
1
2
|
import { Option } from '../core/types.js';
|
|
2
3
|
/**
|
|
3
4
|
* Presentational segmented pill group. Used by the form choice field (bound to a
|
|
4
5
|
* form value) and the core segmented control (standalone, emits an event).
|
|
5
6
|
*/
|
|
6
|
-
export declare function SegmentedPills({ ariaLabel, autoFocus, disabled, name, onSelect, options, tabIndex, value, }: {
|
|
7
|
+
export declare function SegmentedPills({ ariaLabel, autoFocus, className, disabled, name, onSelect, options, tabIndex, value, ...props }: Omit<ComponentProps<"div">, "children" | "onSelect" | "ref"> & {
|
|
7
8
|
ariaLabel?: string;
|
|
8
9
|
autoFocus?: boolean;
|
|
9
10
|
disabled?: boolean;
|
|
@@ -7,7 +7,7 @@ import { jsx } from "react/jsx-runtime";
|
|
|
7
7
|
* Presentational segmented pill group. Used by the form choice field (bound to a
|
|
8
8
|
* form value) and the core segmented control (standalone, emits an event).
|
|
9
9
|
*/
|
|
10
|
-
function SegmentedPills({ ariaLabel, autoFocus = false, disabled = false, name, onSelect, options, tabIndex, value }) {
|
|
10
|
+
function SegmentedPills({ ariaLabel, autoFocus = false, className, disabled = false, name, onSelect, options, tabIndex, value, ...props }) {
|
|
11
11
|
const groupRef = useRef(null);
|
|
12
12
|
useEffect(() => {
|
|
13
13
|
if (!autoFocus) return;
|
|
@@ -15,8 +15,9 @@ function SegmentedPills({ ariaLabel, autoFocus = false, disabled = false, name,
|
|
|
15
15
|
(group?.querySelector("button[aria-checked=\"true\"]") ?? group?.querySelector("button"))?.focus();
|
|
16
16
|
}, [autoFocus]);
|
|
17
17
|
return /* @__PURE__ */ jsx("div", {
|
|
18
|
+
...props,
|
|
18
19
|
"aria-label": ariaLabel,
|
|
19
|
-
className: "inline-flex w-fit max-w-full gap-1 overflow-x-auto rounded-lt bg-lt-muted p-1",
|
|
20
|
+
className: cn("inline-flex w-fit max-w-full gap-1 overflow-x-auto rounded-lt bg-lt-muted p-1", className),
|
|
20
21
|
ref: groupRef,
|
|
21
22
|
role: "radiogroup",
|
|
22
23
|
children: options.map((option) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"segmented-pills.js","names":[],"sources":["../../resources/js/ui/segmented-pills.tsx"],"sourcesContent":["import { useEffect, useRef } from \"react\";\nimport type { Option } from \"@lattice-php/lattice/core/types\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { pillClassName } from \"./pill\";\n\n/**\n * Presentational segmented pill group. Used by the form choice field (bound to a\n * form value) and the core segmented control (standalone, emits an event).\n */\nexport function SegmentedPills({\n ariaLabel,\n autoFocus = false,\n disabled = false,\n name,\n onSelect,\n options,\n tabIndex,\n value,\n}: {\n ariaLabel?: string;\n autoFocus?: boolean;\n disabled?: boolean;\n name: string;\n onSelect: (value: string) => void;\n options: Option[];\n tabIndex?: number;\n value: string;\n}) {\n const groupRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!autoFocus) {\n return;\n }\n\n const group = groupRef.current;\n const target =\n group?.querySelector<HTMLButtonElement>('button[aria-checked=\"true\"]') ??\n group?.querySelector<HTMLButtonElement>(\"button\");\n\n target?.focus();\n }, [autoFocus]);\n\n return (\n <div\n aria-label={ariaLabel}\n className
|
|
1
|
+
{"version":3,"file":"segmented-pills.js","names":[],"sources":["../../resources/js/ui/segmented-pills.tsx"],"sourcesContent":["import { type ComponentProps, useEffect, useRef } from \"react\";\nimport type { Option } from \"@lattice-php/lattice/core/types\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { pillClassName } from \"./pill\";\n\n/**\n * Presentational segmented pill group. Used by the form choice field (bound to a\n * form value) and the core segmented control (standalone, emits an event).\n */\nexport function SegmentedPills({\n ariaLabel,\n autoFocus = false,\n className,\n disabled = false,\n name,\n onSelect,\n options,\n tabIndex,\n value,\n ...props\n}: Omit<ComponentProps<\"div\">, \"children\" | \"onSelect\" | \"ref\"> & {\n ariaLabel?: string;\n autoFocus?: boolean;\n disabled?: boolean;\n name: string;\n onSelect: (value: string) => void;\n options: Option[];\n tabIndex?: number;\n value: string;\n}) {\n const groupRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!autoFocus) {\n return;\n }\n\n const group = groupRef.current;\n const target =\n group?.querySelector<HTMLButtonElement>('button[aria-checked=\"true\"]') ??\n group?.querySelector<HTMLButtonElement>(\"button\");\n\n target?.focus();\n }, [autoFocus]);\n\n return (\n <div\n {...props}\n aria-label={ariaLabel}\n className={cn(\n \"inline-flex w-fit max-w-full gap-1 overflow-x-auto rounded-lt bg-lt-muted p-1\",\n className,\n )}\n ref={groupRef}\n role=\"radiogroup\"\n >\n {options.map((option) => {\n const isSelected = value === option.value;\n\n return (\n <button\n aria-checked={isSelected}\n data-test={`${name}-${option.value}`}\n className={cn(pillClassName(isSelected), disabled && \"cursor-not-allowed opacity-60\")}\n disabled={disabled}\n key={option.value}\n onClick={() => onSelect(option.value)}\n role=\"radio\"\n tabIndex={tabIndex}\n type=\"button\"\n >\n {option.label}\n </button>\n );\n })}\n </div>\n );\n}\n"],"mappings":";;;;;;;;;AASA,SAAgB,eAAe,EAC7B,WACA,YAAY,OACZ,WACA,WAAW,OACX,MACA,UACA,SACA,UACA,OACA,GAAG,SAUF;CACD,MAAM,WAAW,OAAuB,IAAI;CAE5C,gBAAgB;EACd,IAAI,CAAC,WACH;EAGF,MAAM,QAAQ,SAAS;EAKvB,CAHE,OAAO,cAAiC,+BAA6B,KACrE,OAAO,cAAiC,QAAQ,EAAA,EAE1C,MAAM;CAChB,GAAG,CAAC,SAAS,CAAC;CAEd,OACE,oBAAC,OAAD;EACE,GAAI;EACJ,cAAY;EACZ,WAAW,GACT,iFACA,SACF;EACA,KAAK;EACL,MAAK;EAEJ,UAAA,QAAQ,KAAK,WAAW;GACvB,MAAM,aAAa,UAAU,OAAO;GAEpC,OACE,oBAAC,UAAD;IACE,gBAAc;IACd,aAAW,GAAG,KAAK,GAAG,OAAO;IAC7B,WAAW,GAAG,cAAc,UAAU,GAAG,YAAY,+BAA+B;IAC1E;IAEV,eAAe,SAAS,OAAO,KAAK;IACpC,MAAK;IACK;IACV,MAAK;IAEJ,UAAA,OAAO;GACF,GAPD,OAAO,KAON;EAEZ,CAAC;CACE,CAAA;AAET"}
|