@lattice-php/lattice 0.16.0 → 0.17.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/action/components/action-form.js +1 -1
- package/dist/action/use-action.js +1 -1
- package/dist/chat/types.d.ts +2 -10
- package/dist/core/components/button.js +34 -18
- package/dist/core/components/button.js.map +1 -1
- package/dist/core/components/control.d.ts +0 -2
- package/dist/core/components/control.js.map +1 -1
- package/dist/core/components/link.js +25 -29
- package/dist/core/components/link.js.map +1 -1
- package/dist/core/types.d.ts +22 -42
- package/dist/core/use-click-behavior.d.ts +42 -0
- package/dist/core/use-click-behavior.js +46 -0
- package/dist/core/use-click-behavior.js.map +1 -0
- package/dist/create-app.d.ts +8 -2
- package/dist/create-app.js +4 -2
- package/dist/create-app.js.map +1 -1
- package/dist/effects/registry.d.ts +9 -20
- package/dist/effects/registry.js +4 -6
- package/dist/effects/registry.js.map +1 -1
- package/dist/events/event-bridge.d.ts +1 -1
- package/dist/events/event-bridge.js +1 -1
- package/dist/events/event-bridge.js.map +1 -1
- package/dist/form/components/base/input-otp.d.ts +2 -1
- package/dist/form/components/base/input-otp.js.map +1 -1
- package/dist/form/components/conditions.d.ts +1 -1
- package/dist/form/components/conditions.js.map +1 -1
- package/dist/form/components/field-props.d.ts +2 -1
- package/dist/form/components/field-props.js.map +1 -1
- package/dist/form/components/field-scope.d.ts +2 -1
- package/dist/form/components/field-scope.js.map +1 -1
- package/dist/form/components/fields/row-action-menu.d.ts +2 -1
- package/dist/form/components/fields/row-action-menu.js.map +1 -1
- package/dist/form/components/fields/row-item.d.ts +2 -1
- package/dist/form/components/fields/row-item.js.map +1 -1
- package/dist/form/components/fields/table-rows.d.ts +2 -1
- package/dist/form/components/fields/table-rows.js.map +1 -1
- package/dist/form/components/fields/time-picker-columns.d.ts +2 -1
- package/dist/form/components/fields/time-picker-columns.js.map +1 -1
- package/dist/form/components/fields/time-picker.d.ts +2 -1
- package/dist/form/components/fields/time-picker.js.map +1 -1
- package/dist/form/components/fields/use-row-collection.d.ts +2 -1
- package/dist/form/components/fields/use-row-collection.js.map +1 -1
- package/dist/form/components/form-path.d.ts +0 -1
- package/dist/form/components/form-path.js +1 -1
- package/dist/form/components/form-path.js.map +1 -1
- package/dist/form/components/prefill-targets.d.ts +1 -1
- package/dist/form/components/prefill-targets.js.map +1 -1
- package/dist/form/components/types.d.ts +5 -1
- package/dist/form/components/use-field-commit.d.ts +2 -1
- package/dist/form/components/use-field-commit.js.map +1 -1
- package/dist/form/components/use-form-resolver.d.ts +2 -1
- package/dist/form/components/use-form-resolver.js.map +1 -1
- package/dist/format/date-time.d.ts +12 -0
- package/dist/format/date-time.js +30 -0
- package/dist/format/date-time.js.map +1 -0
- package/dist/format/value.js +1 -1
- package/dist/format/value.js.map +1 -1
- package/dist/i18n/config.d.ts +2 -1
- package/dist/i18n/config.js.map +1 -1
- package/dist/i18n/date-time.js +1 -1
- package/dist/i18n/date-time.js.map +1 -1
- package/dist/i18n/instance.d.ts +1 -1
- package/dist/i18n/instance.js.map +1 -1
- package/dist/i18n/locale-reload.d.ts +2 -1
- package/dist/i18n/locale-reload.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/layout/components.js +1 -1
- package/dist/layout/menu-item.js +43 -49
- package/dist/layout/menu-item.js.map +1 -1
- package/dist/notifications/api.d.ts +6 -0
- package/dist/notifications/api.js +21 -0
- package/dist/notifications/api.js.map +1 -0
- package/dist/notifications/components/empty-state.d.ts +1 -0
- package/dist/notifications/components/empty-state.js +21 -0
- package/dist/notifications/components/empty-state.js.map +1 -0
- package/dist/notifications/components/notification-item.d.ts +6 -0
- package/dist/notifications/components/notification-item.js +65 -0
- package/dist/notifications/components/notification-item.js.map +1 -0
- package/dist/notifications/components/notification-list.d.ts +10 -0
- package/dist/notifications/components/notification-list.js +38 -0
- package/dist/notifications/components/notification-list.js.map +1 -0
- package/dist/notifications/components/notifications-echo.d.ts +5 -0
- package/dist/notifications/components/notifications-echo.js +22 -0
- package/dist/notifications/components/notifications-echo.js.map +1 -0
- package/dist/notifications/components/notifications.d.ts +3 -0
- package/dist/notifications/components/notifications.js +109 -0
- package/dist/notifications/components/notifications.js.map +1 -0
- package/dist/notifications/index.d.ts +1 -0
- package/dist/notifications/index.js +11 -0
- package/dist/notifications/index.js.map +1 -0
- package/dist/notifications/store.d.ts +25 -0
- package/dist/notifications/store.js +100 -0
- package/dist/notifications/store.js.map +1 -0
- package/dist/notifications/types.d.ts +10 -0
- package/dist/notifications/types.js +0 -0
- package/dist/realtime/build-effects.d.ts +2 -1
- package/dist/realtime/build-effects.js.map +1 -1
- package/dist/realtime/subscriptions.js.map +1 -1
- package/dist/registry/eager.js +2 -1
- package/dist/registry/eager.js.map +1 -1
- package/dist/registry/lazy.js +2 -1
- package/dist/registry/lazy.js.map +1 -1
- package/dist/table/bulk.d.ts +2 -1
- package/dist/table/bulk.js.map +1 -1
- package/dist/table/components/bulk-bar.js +2 -2
- package/dist/table/components/cells/money-cell.js +1 -1
- package/dist/table/components/cells/number-cell.js +1 -1
- package/dist/table/components/cells/text-cell.js +1 -1
- package/dist/table/components/filter-controls.d.ts +0 -4
- package/dist/table/components/filter-controls.js.map +1 -1
- package/dist/table/components/table-cell.js.map +1 -1
- package/dist/table/format.d.ts +1 -12
- package/dist/table/format.js +2 -26
- package/dist/table/format.js.map +1 -1
- package/dist/table/types.d.ts +7 -17
- package/dist/types/generated.d.ts +119 -290
- package/dist/vite-client.d.ts +8 -0
- package/dist/vite.d.ts +35 -1
- package/dist/vite.js +60 -2
- package/dist/vite.js.map +1 -1
- package/package.json +13 -2
- package/resources/icons/bell.svg +16 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { cn } from "../../../lib/utils.js";
|
|
2
|
-
import { formatCell, resolveLink } from "../../format.js";
|
|
3
2
|
import { DateTime } from "../../../i18n/date-time.js";
|
|
4
3
|
import { CopyableText } from "../../../clipboard/copyable-text.js";
|
|
4
|
+
import { formatCell, resolveLink } from "../../format.js";
|
|
5
5
|
import { jsx } from "react/jsx-runtime";
|
|
6
6
|
//#region resources/js/table/components/cells/text-cell.tsx
|
|
7
7
|
var TextCell = (args) => {
|
|
@@ -1,8 +1,4 @@
|
|
|
1
1
|
import { FilterData, Option } from '../../types/generated';
|
|
2
|
-
export type DateRangeValue = {
|
|
3
|
-
from?: string;
|
|
4
|
-
until?: string;
|
|
5
|
-
};
|
|
6
2
|
export type FilterOptionSearch = (query: string) => Promise<Option[]>;
|
|
7
3
|
/**
|
|
8
4
|
* Renders the control for a single dedicated table filter, dispatching on the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filter-controls.js","names":[],"sources":["../../../resources/js/table/components/filter-controls.tsx"],"sourcesContent":["import { Icon } from \"@lattice-php/lattice/icons\";\nimport { useState } from \"react\";\nimport { Checkbox } from \"@lattice-php/lattice/core/components/checkbox\";\nimport { Combobox } from \"@lattice-php/lattice/core/components/combobox\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport type { FilterData, Option } from \"@lattice-php/lattice/types/generated\";\nimport { filterOptions, stringProp } from \"../filter-values\";\nimport { fieldClass } from \"./filter-value-input\";\n\nexport type DateRangeValue = { from?: string; until?: string };\n\nexport type FilterOptionSearch = (query: string) => Promise<Option[]>;\n\n/**\n * Renders the control for a single dedicated table filter, dispatching on the\n * filter's `type`. The current value comes from the table state; `onChange`\n * pushes a new value (an empty value clears the filter).\n */\nexport function TableFilterControl({\n filter,\n value,\n processing,\n onChange,\n onSearch,\n}: {\n filter: FilterData;\n value: unknown;\n processing: boolean;\n onChange: (value: unknown) => void;\n onSearch?: FilterOptionSearch;\n}) {\n switch (filter.type) {\n case \"select\":\n if (filter.props.searchable === true && onSearch) {\n return (\n <SearchableSelectControl\n filter={filter}\n value={value}\n processing={processing}\n onChange={onChange}\n onSearch={onSearch}\n />\n );\n }\n\n return filter.props.multiple === true ? (\n <MultiSelectControl\n filter={filter}\n value={value}\n processing={processing}\n onChange={onChange}\n />\n ) : (\n <SelectControl filter={filter} value={value} processing={processing} onChange={onChange} />\n );\n case \"ternary\":\n return (\n <TernaryControl filter={filter} value={value} processing={processing} onChange={onChange} />\n );\n case \"date-range\":\n return (\n <DateRangeControl\n filter={filter}\n value={value}\n processing={processing}\n onChange={onChange}\n />\n );\n case \"toggle\":\n return (\n <ToggleControl filter={filter} value={value} processing={processing} onChange={onChange} />\n );\n default:\n return null;\n }\n}\n\nfunction SelectControl({\n filter,\n value,\n processing,\n onChange,\n}: {\n filter: FilterData;\n value: unknown;\n processing: boolean;\n onChange: (value: unknown) => void;\n}) {\n const { t } = useT(\"lattice\");\n const placeholder = stringProp(filter, \"placeholder\", t(\"table.filter.all\", \"All\"));\n\n return (\n <select\n aria-label={filter.label}\n data-test={`table-filter-${filter.key}`}\n className={fieldClass}\n disabled={processing}\n value={typeof value === \"string\" ? value : \"\"}\n onChange={(event) => onChange(event.target.value)}\n >\n <option value=\"\">{placeholder}</option>\n {filterOptions(filter).map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n );\n}\n\nfunction MultiSelectControl({\n filter,\n value,\n processing,\n onChange,\n}: {\n filter: FilterData;\n value: unknown;\n processing: boolean;\n onChange: (value: unknown) => void;\n}) {\n const { t } = useT(\"lattice\");\n const [open, setOpen] = useState(false);\n const selected = Array.isArray(value) ? (value as string[]) : [];\n\n function toggle(optionValue: string): void {\n const next = selected.includes(optionValue)\n ? selected.filter((item) => item !== optionValue)\n : [...selected, optionValue];\n\n onChange(next);\n }\n\n const summary =\n selected.length === 0\n ? stringProp(filter, \"placeholder\", t(\"table.filter.all\", \"All\"))\n : t(\"table.filter.selectedCount\", \"{{amount}} selected\", { amount: selected.length });\n\n return (\n <div className=\"relative\">\n <button\n type=\"button\"\n aria-label={filter.label}\n aria-expanded={open}\n data-test={`table-filter-${filter.key}`}\n className={`${fieldClass} flex items-center justify-between gap-2`}\n disabled={processing}\n onClick={() => setOpen((current) => !current)}\n >\n <span className=\"truncate\">{summary}</span>\n <Icon name=\"chevron-down\" aria-hidden=\"true\" className=\"size-lt-icon-sm shrink-0\" />\n </button>\n {open && (\n <div className=\"absolute z-lt-dropdown mt-1 min-w-full rounded-lt-sm border border-lt-border bg-lt-bg p-1 shadow-lt-md\">\n {filterOptions(filter).map((option) => (\n <label\n key={option.value}\n className=\"flex cursor-pointer items-center gap-2 rounded-lt-sm px-2 py-1.5 text-sm hover:bg-lt-muted\"\n >\n <Checkbox\n aria-label={option.label}\n data-test={`table-filter-${filter.key}-${option.value}`}\n checked={selected.includes(option.value)}\n disabled={processing}\n onCheckedChange={() => toggle(option.value)}\n />\n <span className=\"truncate\">{option.label}</span>\n </label>\n ))}\n </div>\n )}\n </div>\n );\n}\n\nfunction SearchableSelectControl({\n filter,\n value,\n processing,\n onChange,\n onSearch,\n}: {\n filter: FilterData;\n value: unknown;\n processing: boolean;\n onChange: (value: unknown) => void;\n onSearch: FilterOptionSearch;\n}) {\n const { t } = useT(\"lattice\");\n const multiple = filter.props.multiple === true;\n const [open, setOpen] = useState(false);\n const [results, setResults] = useState<Option[]>(() => filterOptions(filter));\n const [loading, setLoading] = useState(false);\n\n const selected = multiple\n ? Array.isArray(value)\n ? (value as string[])\n : []\n : typeof value === \"string\" && value !== \"\"\n ? [value]\n : [];\n\n const labels = new Map(\n [...filterOptions(filter), ...results].map((option) => [option.value, option.label]),\n );\n const summary =\n selected.length === 0\n ? stringProp(filter, \"placeholder\", t(\"table.filter.all\", \"All\"))\n : multiple\n ? t(\"table.filter.selectedCount\", \"{{amount}} selected\", { amount: selected.length })\n : (labels.get(selected[0]) ?? selected[0]);\n\n function search(query: string): void {\n setLoading(true);\n void onSearch(query).then((options) => {\n setResults(options);\n setLoading(false);\n });\n }\n\n function choose(optionValue: string): void {\n onChange(\n multiple\n ? selected.includes(optionValue)\n ? selected.filter((item) => item !== optionValue)\n : [...selected, optionValue]\n : optionValue,\n );\n }\n\n return (\n <Combobox\n contentClassName=\"w-60\"\n loading={loading}\n multiple={multiple}\n onSearch={search}\n onSelect={choose}\n open={open}\n onOpenChange={setOpen}\n options={results}\n searchLabel={t(\"table.filter.search\", \"Search\")}\n selected={selected}\n testId={`table-filter-${filter.key}`}\n trigger={\n <>\n <span className=\"truncate\">{summary}</span>\n <Icon name=\"chevron-down\" aria-hidden=\"true\" className=\"size-lt-icon-sm shrink-0\" />\n </>\n }\n triggerClassName={cn(fieldClass, \"flex items-center justify-between gap-2\")}\n triggerProps={{\n \"aria-label\": filter.label,\n \"data-test\": `table-filter-${filter.key}`,\n disabled: processing,\n }}\n />\n );\n}\n\nfunction TernaryControl({\n filter,\n value,\n processing,\n onChange,\n}: {\n filter: FilterData;\n value: unknown;\n processing: boolean;\n onChange: (value: unknown) => void;\n}) {\n const { t } = useT(\"lattice\");\n const placeholder = stringProp(filter, \"placeholder\", t(\"table.filter.all\", \"All\"));\n const trueLabel = stringProp(filter, \"trueLabel\", t(\"table.filter.true\", \"True\"));\n const falseLabel = stringProp(filter, \"falseLabel\", t(\"table.filter.false\", \"False\"));\n\n return (\n <select\n aria-label={filter.label}\n data-test={`table-filter-${filter.key}`}\n className={fieldClass}\n disabled={processing}\n value={typeof value === \"string\" ? value : \"\"}\n onChange={(event) => onChange(event.target.value)}\n >\n <option value=\"\">{placeholder}</option>\n <option value=\"true\">{trueLabel}</option>\n <option value=\"false\">{falseLabel}</option>\n </select>\n );\n}\n\nfunction DateRangeControl({\n filter,\n value,\n processing,\n onChange,\n}: {\n filter: FilterData;\n value: unknown;\n processing: boolean;\n onChange: (value: unknown) => void;\n}) {\n const { t } = useT(\"lattice\");\n const range: DateRangeValue = value && typeof value === \"object\" ? (value as DateRangeValue) : {};\n\n function commit(next: DateRangeValue): void {\n onChange({ from: next.from ?? \"\", until: next.until ?? \"\" });\n }\n\n return (\n <div className=\"flex items-center gap-1\">\n <input\n type=\"date\"\n aria-label={t(\"table.filter.from\", \"{{label}} from\", { label: filter.label })}\n data-test={`table-filter-${filter.key}-from`}\n className={fieldClass}\n disabled={processing}\n value={range.from ?? \"\"}\n onChange={(event) => commit({ ...range, from: event.target.value })}\n />\n <span className=\"text-lt-muted-fg\" aria-hidden=\"true\">\n –\n </span>\n <input\n type=\"date\"\n aria-label={t(\"table.filter.until\", \"{{label}} until\", { label: filter.label })}\n data-test={`table-filter-${filter.key}-until`}\n className={fieldClass}\n disabled={processing}\n value={range.until ?? \"\"}\n onChange={(event) => commit({ ...range, until: event.target.value })}\n />\n </div>\n );\n}\n\nfunction ToggleControl({\n filter,\n value,\n processing,\n onChange,\n}: {\n filter: FilterData;\n value: unknown;\n processing: boolean;\n onChange: (value: unknown) => void;\n}) {\n const checked = value === \"1\" || value === true || value === \"true\";\n\n return (\n <label className=\"flex h-lt-control-md cursor-pointer items-center gap-2 text-sm\">\n <Checkbox\n aria-label={filter.label}\n data-test={`table-filter-${filter.key}`}\n checked={checked}\n disabled={processing}\n onCheckedChange={(next) => onChange(next === true ? \"1\" : \"\")}\n />\n <span>{filter.label}</span>\n </label>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"filter-controls.js","names":[],"sources":["../../../resources/js/table/components/filter-controls.tsx"],"sourcesContent":["import { Icon } from \"@lattice-php/lattice/icons\";\nimport { useState } from \"react\";\nimport { Checkbox } from \"@lattice-php/lattice/core/components/checkbox\";\nimport { Combobox } from \"@lattice-php/lattice/core/components/combobox\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport type { FilterData, Option } from \"@lattice-php/lattice/types/generated\";\nimport { filterOptions, stringProp } from \"../filter-values\";\nimport { fieldClass } from \"./filter-value-input\";\n\ntype DateRangeValue = { from?: string; until?: string };\n\nexport type FilterOptionSearch = (query: string) => Promise<Option[]>;\n\n/**\n * Renders the control for a single dedicated table filter, dispatching on the\n * filter's `type`. The current value comes from the table state; `onChange`\n * pushes a new value (an empty value clears the filter).\n */\nexport function TableFilterControl({\n filter,\n value,\n processing,\n onChange,\n onSearch,\n}: {\n filter: FilterData;\n value: unknown;\n processing: boolean;\n onChange: (value: unknown) => void;\n onSearch?: FilterOptionSearch;\n}) {\n switch (filter.type) {\n case \"select\":\n if (filter.props.searchable === true && onSearch) {\n return (\n <SearchableSelectControl\n filter={filter}\n value={value}\n processing={processing}\n onChange={onChange}\n onSearch={onSearch}\n />\n );\n }\n\n return filter.props.multiple === true ? (\n <MultiSelectControl\n filter={filter}\n value={value}\n processing={processing}\n onChange={onChange}\n />\n ) : (\n <SelectControl filter={filter} value={value} processing={processing} onChange={onChange} />\n );\n case \"ternary\":\n return (\n <TernaryControl filter={filter} value={value} processing={processing} onChange={onChange} />\n );\n case \"date-range\":\n return (\n <DateRangeControl\n filter={filter}\n value={value}\n processing={processing}\n onChange={onChange}\n />\n );\n case \"toggle\":\n return (\n <ToggleControl filter={filter} value={value} processing={processing} onChange={onChange} />\n );\n default:\n return null;\n }\n}\n\nfunction SelectControl({\n filter,\n value,\n processing,\n onChange,\n}: {\n filter: FilterData;\n value: unknown;\n processing: boolean;\n onChange: (value: unknown) => void;\n}) {\n const { t } = useT(\"lattice\");\n const placeholder = stringProp(filter, \"placeholder\", t(\"table.filter.all\", \"All\"));\n\n return (\n <select\n aria-label={filter.label}\n data-test={`table-filter-${filter.key}`}\n className={fieldClass}\n disabled={processing}\n value={typeof value === \"string\" ? value : \"\"}\n onChange={(event) => onChange(event.target.value)}\n >\n <option value=\"\">{placeholder}</option>\n {filterOptions(filter).map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n );\n}\n\nfunction MultiSelectControl({\n filter,\n value,\n processing,\n onChange,\n}: {\n filter: FilterData;\n value: unknown;\n processing: boolean;\n onChange: (value: unknown) => void;\n}) {\n const { t } = useT(\"lattice\");\n const [open, setOpen] = useState(false);\n const selected = Array.isArray(value) ? (value as string[]) : [];\n\n function toggle(optionValue: string): void {\n const next = selected.includes(optionValue)\n ? selected.filter((item) => item !== optionValue)\n : [...selected, optionValue];\n\n onChange(next);\n }\n\n const summary =\n selected.length === 0\n ? stringProp(filter, \"placeholder\", t(\"table.filter.all\", \"All\"))\n : t(\"table.filter.selectedCount\", \"{{amount}} selected\", { amount: selected.length });\n\n return (\n <div className=\"relative\">\n <button\n type=\"button\"\n aria-label={filter.label}\n aria-expanded={open}\n data-test={`table-filter-${filter.key}`}\n className={`${fieldClass} flex items-center justify-between gap-2`}\n disabled={processing}\n onClick={() => setOpen((current) => !current)}\n >\n <span className=\"truncate\">{summary}</span>\n <Icon name=\"chevron-down\" aria-hidden=\"true\" className=\"size-lt-icon-sm shrink-0\" />\n </button>\n {open && (\n <div className=\"absolute z-lt-dropdown mt-1 min-w-full rounded-lt-sm border border-lt-border bg-lt-bg p-1 shadow-lt-md\">\n {filterOptions(filter).map((option) => (\n <label\n key={option.value}\n className=\"flex cursor-pointer items-center gap-2 rounded-lt-sm px-2 py-1.5 text-sm hover:bg-lt-muted\"\n >\n <Checkbox\n aria-label={option.label}\n data-test={`table-filter-${filter.key}-${option.value}`}\n checked={selected.includes(option.value)}\n disabled={processing}\n onCheckedChange={() => toggle(option.value)}\n />\n <span className=\"truncate\">{option.label}</span>\n </label>\n ))}\n </div>\n )}\n </div>\n );\n}\n\nfunction SearchableSelectControl({\n filter,\n value,\n processing,\n onChange,\n onSearch,\n}: {\n filter: FilterData;\n value: unknown;\n processing: boolean;\n onChange: (value: unknown) => void;\n onSearch: FilterOptionSearch;\n}) {\n const { t } = useT(\"lattice\");\n const multiple = filter.props.multiple === true;\n const [open, setOpen] = useState(false);\n const [results, setResults] = useState<Option[]>(() => filterOptions(filter));\n const [loading, setLoading] = useState(false);\n\n const selected = multiple\n ? Array.isArray(value)\n ? (value as string[])\n : []\n : typeof value === \"string\" && value !== \"\"\n ? [value]\n : [];\n\n const labels = new Map(\n [...filterOptions(filter), ...results].map((option) => [option.value, option.label]),\n );\n const summary =\n selected.length === 0\n ? stringProp(filter, \"placeholder\", t(\"table.filter.all\", \"All\"))\n : multiple\n ? t(\"table.filter.selectedCount\", \"{{amount}} selected\", { amount: selected.length })\n : (labels.get(selected[0]) ?? selected[0]);\n\n function search(query: string): void {\n setLoading(true);\n void onSearch(query).then((options) => {\n setResults(options);\n setLoading(false);\n });\n }\n\n function choose(optionValue: string): void {\n onChange(\n multiple\n ? selected.includes(optionValue)\n ? selected.filter((item) => item !== optionValue)\n : [...selected, optionValue]\n : optionValue,\n );\n }\n\n return (\n <Combobox\n contentClassName=\"w-60\"\n loading={loading}\n multiple={multiple}\n onSearch={search}\n onSelect={choose}\n open={open}\n onOpenChange={setOpen}\n options={results}\n searchLabel={t(\"table.filter.search\", \"Search\")}\n selected={selected}\n testId={`table-filter-${filter.key}`}\n trigger={\n <>\n <span className=\"truncate\">{summary}</span>\n <Icon name=\"chevron-down\" aria-hidden=\"true\" className=\"size-lt-icon-sm shrink-0\" />\n </>\n }\n triggerClassName={cn(fieldClass, \"flex items-center justify-between gap-2\")}\n triggerProps={{\n \"aria-label\": filter.label,\n \"data-test\": `table-filter-${filter.key}`,\n disabled: processing,\n }}\n />\n );\n}\n\nfunction TernaryControl({\n filter,\n value,\n processing,\n onChange,\n}: {\n filter: FilterData;\n value: unknown;\n processing: boolean;\n onChange: (value: unknown) => void;\n}) {\n const { t } = useT(\"lattice\");\n const placeholder = stringProp(filter, \"placeholder\", t(\"table.filter.all\", \"All\"));\n const trueLabel = stringProp(filter, \"trueLabel\", t(\"table.filter.true\", \"True\"));\n const falseLabel = stringProp(filter, \"falseLabel\", t(\"table.filter.false\", \"False\"));\n\n return (\n <select\n aria-label={filter.label}\n data-test={`table-filter-${filter.key}`}\n className={fieldClass}\n disabled={processing}\n value={typeof value === \"string\" ? value : \"\"}\n onChange={(event) => onChange(event.target.value)}\n >\n <option value=\"\">{placeholder}</option>\n <option value=\"true\">{trueLabel}</option>\n <option value=\"false\">{falseLabel}</option>\n </select>\n );\n}\n\nfunction DateRangeControl({\n filter,\n value,\n processing,\n onChange,\n}: {\n filter: FilterData;\n value: unknown;\n processing: boolean;\n onChange: (value: unknown) => void;\n}) {\n const { t } = useT(\"lattice\");\n const range: DateRangeValue = value && typeof value === \"object\" ? (value as DateRangeValue) : {};\n\n function commit(next: DateRangeValue): void {\n onChange({ from: next.from ?? \"\", until: next.until ?? \"\" });\n }\n\n return (\n <div className=\"flex items-center gap-1\">\n <input\n type=\"date\"\n aria-label={t(\"table.filter.from\", \"{{label}} from\", { label: filter.label })}\n data-test={`table-filter-${filter.key}-from`}\n className={fieldClass}\n disabled={processing}\n value={range.from ?? \"\"}\n onChange={(event) => commit({ ...range, from: event.target.value })}\n />\n <span className=\"text-lt-muted-fg\" aria-hidden=\"true\">\n –\n </span>\n <input\n type=\"date\"\n aria-label={t(\"table.filter.until\", \"{{label}} until\", { label: filter.label })}\n data-test={`table-filter-${filter.key}-until`}\n className={fieldClass}\n disabled={processing}\n value={range.until ?? \"\"}\n onChange={(event) => commit({ ...range, until: event.target.value })}\n />\n </div>\n );\n}\n\nfunction ToggleControl({\n filter,\n value,\n processing,\n onChange,\n}: {\n filter: FilterData;\n value: unknown;\n processing: boolean;\n onChange: (value: unknown) => void;\n}) {\n const checked = value === \"1\" || value === true || value === \"true\";\n\n return (\n <label className=\"flex h-lt-control-md cursor-pointer items-center gap-2 text-sm\">\n <Checkbox\n aria-label={filter.label}\n data-test={`table-filter-${filter.key}`}\n checked={checked}\n disabled={processing}\n onCheckedChange={(next) => onChange(next === true ? \"1\" : \"\")}\n />\n <span>{filter.label}</span>\n </label>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"table-cell.js","names":[],"sources":["../../../resources/js/table/components/table-cell.tsx"],"sourcesContent":["import { useColumnRegistry } from \"
|
|
1
|
+
{"version":3,"file":"table-cell.js","names":[],"sources":["../../../resources/js/table/components/table-cell.tsx"],"sourcesContent":["import { useColumnRegistry } from \"@lattice-php/lattice/core/registry-context\";\nimport { columnCell, type ColumnRegistry } from \"../registry\";\nimport type { TableColumn, TableRow } from \"../types\";\nimport { BadgeCell } from \"./cells/badge-cell\";\nimport { BooleanCell } from \"./cells/boolean-cell\";\nimport { IconCell } from \"./cells/icon-cell\";\nimport { ImageCell } from \"./cells/image-cell\";\nimport { MoneyCell } from \"./cells/money-cell\";\nimport { NumberCell } from \"./cells/number-cell\";\nimport { StackCell } from \"./cells/stack-cell\";\nimport { TextCell } from \"./cells/text-cell\";\n\n// Built-in cells live with the (lazy-loaded) table feature rather than the\n// eager registry, so they stay code-split. Consumer-registered columns are\n// merged on top and win on type collisions.\nconst builtinColumnCells: ColumnRegistry = {\n \"column.badge\": columnCell(BadgeCell),\n \"column.boolean\": columnCell(BooleanCell),\n \"column.icon\": columnCell(IconCell),\n \"column.image\": columnCell(ImageCell),\n \"column.money\": columnCell(MoneyCell),\n \"column.number\": columnCell(NumberCell),\n \"column.stack\": columnCell(StackCell),\n \"column.text\": columnCell(TextCell),\n};\n\nexport function ColumnCell({ column, row }: { column: TableColumn; row: TableRow }) {\n const customCells = useColumnRegistry();\n const Cell =\n customCells[column.type] ??\n builtinColumnCells[column.type] ??\n builtinColumnCells[\"column.text\"];\n\n return <Cell column={column} props={column.props ?? {}} row={row} value={row[column.key]} />;\n}\n"],"mappings":";;;;;;;;;;;;AAeA,IAAM,qBAAqC;CACzC,gBAAgB,WAAW,SAAS;CACpC,kBAAkB,WAAW,WAAW;CACxC,eAAe,WAAW,QAAQ;CAClC,gBAAgB,WAAW,SAAS;CACpC,gBAAgB,WAAW,SAAS;CACpC,iBAAiB,WAAW,UAAU;CACtC,gBAAgB,WAAW,SAAS;CACpC,eAAe,WAAW,QAAQ;AACpC;AAEA,SAAgB,WAAW,EAAE,QAAQ,OAA+C;CAOlF,OAAO,oBANa,kBAElB,EAAY,OAAO,SACnB,mBAAmB,OAAO,SAC1B,mBAAmB,gBAEd;EAAc;EAAQ,OAAO,OAAO,SAAS,CAAC;EAAQ;EAAK,OAAO,IAAI,OAAO;CAAO,CAAA;AAC7F"}
|
package/dist/table/format.d.ts
CHANGED
|
@@ -1,15 +1,4 @@
|
|
|
1
|
+
import { FormatOptions } from '../format/date-time';
|
|
1
2
|
import { TableColumn, TableRow } from './types';
|
|
2
|
-
export type FormatOptions = {
|
|
3
|
-
locale?: string;
|
|
4
|
-
timeZone?: string;
|
|
5
|
-
};
|
|
6
|
-
export type DateConfig = {
|
|
7
|
-
dateStyle: string | null;
|
|
8
|
-
timeStyle: string | null;
|
|
9
|
-
month?: string | null;
|
|
10
|
-
year?: string | null;
|
|
11
|
-
};
|
|
12
3
|
export declare function formatCell(value: unknown, column?: TableColumn, options?: FormatOptions): string;
|
|
13
|
-
export declare function formatDateValue(value: unknown, date: DateConfig, options?: FormatOptions): string;
|
|
14
|
-
export declare function preciseDateTime(value: unknown, options?: FormatOptions): string;
|
|
15
4
|
export declare function resolveLink(column: TableColumn, row: TableRow, value: unknown): string | null;
|
package/dist/table/format.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { formatDateValue } from "../format/date-time.js";
|
|
1
2
|
//#region resources/js/table/format.ts
|
|
2
3
|
function formatCell(value, column, options) {
|
|
3
4
|
if (value === null || value === void 0) return "";
|
|
@@ -6,31 +7,6 @@ function formatCell(value, column, options) {
|
|
|
6
7
|
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") return String(value);
|
|
7
8
|
return JSON.stringify(value);
|
|
8
9
|
}
|
|
9
|
-
function formatDateValue(value, date, options) {
|
|
10
|
-
const parsed = new Date(String(value));
|
|
11
|
-
if (Number.isNaN(parsed.getTime())) return String(value ?? "");
|
|
12
|
-
const intl = { timeZone: options?.timeZone };
|
|
13
|
-
if (date.dateStyle) intl.dateStyle = date.dateStyle;
|
|
14
|
-
if (date.timeStyle) intl.timeStyle = date.timeStyle;
|
|
15
|
-
if (date.month) intl.month = date.month;
|
|
16
|
-
if (date.year) intl.year = date.year;
|
|
17
|
-
return new Intl.DateTimeFormat(options?.locale, intl).format(parsed);
|
|
18
|
-
}
|
|
19
|
-
function preciseDateTime(value, options) {
|
|
20
|
-
const date = new Date(String(value));
|
|
21
|
-
if (Number.isNaN(date.getTime())) return "";
|
|
22
|
-
const formatted = new Intl.DateTimeFormat(options?.locale, {
|
|
23
|
-
year: "numeric",
|
|
24
|
-
month: "short",
|
|
25
|
-
day: "numeric",
|
|
26
|
-
hour: "2-digit",
|
|
27
|
-
minute: "2-digit",
|
|
28
|
-
second: "2-digit",
|
|
29
|
-
timeZone: options?.timeZone,
|
|
30
|
-
timeZoneName: "short"
|
|
31
|
-
}).format(date);
|
|
32
|
-
return options?.timeZone ? `${formatted} (${options.timeZone})` : formatted;
|
|
33
|
-
}
|
|
34
10
|
function resolveLink(column, row, value) {
|
|
35
11
|
const link = column.props?.link;
|
|
36
12
|
if (!link) return null;
|
|
@@ -42,6 +18,6 @@ function resolveLink(column, row, value) {
|
|
|
42
18
|
});
|
|
43
19
|
}
|
|
44
20
|
//#endregion
|
|
45
|
-
export { formatCell,
|
|
21
|
+
export { formatCell, resolveLink };
|
|
46
22
|
|
|
47
23
|
//# sourceMappingURL=format.js.map
|
package/dist/table/format.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format.js","names":[],"sources":["../../resources/js/table/format.ts"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"file":"format.js","names":[],"sources":["../../resources/js/table/format.ts"],"sourcesContent":["import { type FormatOptions, formatDateValue } from \"@lattice-php/lattice/format/date-time\";\nimport type { ColumnPropsOf, TableColumn, TableRow } from \"./types\";\n\nexport function formatCell(value: unknown, column?: TableColumn, options?: FormatOptions): string {\n if (value === null || value === undefined) {\n return \"\";\n }\n\n const date = (column?.props as ColumnPropsOf<\"column.text\"> | null)?.date;\n\n if (date) {\n return formatDateValue(value, date, options);\n }\n\n if (typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\") {\n return String(value);\n }\n\n return JSON.stringify(value);\n}\n\nexport function resolveLink(column: TableColumn, row: TableRow, value: unknown): string | null {\n const link = (column.props as ColumnPropsOf<\"column.text\"> | null)?.link;\n\n if (!link) {\n return null;\n }\n\n const href = link.href ?? String(value ?? \"\");\n\n if (href === \"\") {\n return null;\n }\n\n return href.replace(/\\{([^}]+)\\}/g, (_, key: string) => {\n if (key === \"value\") {\n return encodeURIComponent(String(value ?? \"\"));\n }\n\n return encodeURIComponent(String(row[key] ?? \"\"));\n });\n}\n"],"mappings":";;AAGA,SAAgB,WAAW,OAAgB,QAAsB,SAAiC;CAChG,IAAI,UAAU,QAAQ,UAAU,KAAA,GAC9B,OAAO;CAGT,MAAM,QAAQ,QAAQ,QAA+C;CAErE,IAAI,MACF,OAAO,gBAAgB,OAAO,MAAM,OAAO;CAG7C,IAAI,OAAO,UAAU,YAAY,OAAO,UAAU,YAAY,OAAO,UAAU,WAC7E,OAAO,OAAO,KAAK;CAGrB,OAAO,KAAK,UAAU,KAAK;AAC7B;AAEA,SAAgB,YAAY,QAAqB,KAAe,OAA+B;CAC7F,MAAM,OAAQ,OAAO,OAA+C;CAEpE,IAAI,CAAC,MACH,OAAO;CAGT,MAAM,OAAO,KAAK,QAAQ,OAAO,SAAS,EAAE;CAE5C,IAAI,SAAS,IACX,OAAO;CAGT,OAAO,KAAK,QAAQ,iBAAiB,GAAG,QAAgB;EACtD,IAAI,QAAQ,SACV,OAAO,mBAAmB,OAAO,SAAS,EAAE,CAAC;EAG/C,OAAO,mBAAmB,OAAO,IAAI,QAAQ,EAAE,CAAC;CAClD,CAAC;AACH"}
|
package/dist/table/types.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { ResolveProps } from '../core/types';
|
|
2
|
-
import {
|
|
1
|
+
import { NodeUnionOf, ResolveProps } from '../core/types';
|
|
2
|
+
import { ActionNodeType, ColumnData, ColumnFilter, ColumnPropsMap, ColumnType, FilterClause as WireFilterClause, Op, Table, TablePagination, TableQuery, TableSort } from '../types/generated';
|
|
3
3
|
export type { ColumnData, ColumnFilter, ColumnType, TablePagination, TableSort };
|
|
4
|
+
export type ActionNode = NodeUnionOf<ActionNodeType>;
|
|
4
5
|
export type TableColumn = ColumnData;
|
|
5
6
|
export type TableRow = Record<string, unknown>;
|
|
6
7
|
/**
|
|
@@ -11,10 +12,6 @@ export type TableRow = Record<string, unknown>;
|
|
|
11
12
|
export type FilterClause = Omit<WireFilterClause, "operator"> & {
|
|
12
13
|
operator: Op;
|
|
13
14
|
};
|
|
14
|
-
/**
|
|
15
|
-
* The wire `TableQuery` state, with `filters` narrowed to the client `FilterClause`
|
|
16
|
-
* (known `Op` operator) instead of the wire's free-string operator.
|
|
17
|
-
*/
|
|
18
15
|
export type TableState = Omit<TableQuery, "filters"> & {
|
|
19
16
|
filters: FilterClause[];
|
|
20
17
|
};
|
|
@@ -23,10 +20,7 @@ export type TableResponse = {
|
|
|
23
20
|
pagination?: TablePagination;
|
|
24
21
|
state?: Partial<TableState>;
|
|
25
22
|
};
|
|
26
|
-
/**
|
|
27
|
-
* The table node as it reaches the client: the generated wire props plus the
|
|
28
|
-
* rows, pagination, and state the server hydrates onto it for the initial render.
|
|
29
|
-
*/
|
|
23
|
+
/** The generated wire props plus the rows/pagination/state the server hydrates on for the first render. */
|
|
30
24
|
export type TableNodeProps = Partial<Omit<Table, "bulkActions">> & {
|
|
31
25
|
bulkActions?: ActionNode[];
|
|
32
26
|
data?: TableRow[];
|
|
@@ -40,14 +34,10 @@ export type TableNode = {
|
|
|
40
34
|
props?: TableNodeProps;
|
|
41
35
|
};
|
|
42
36
|
/**
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
37
|
+
* Consumer apps augment this via `declare module "@lattice-php/lattice"` to type
|
|
38
|
+
* their custom columns' props; built-ins resolve through `ColumnPropsMap`. The
|
|
39
|
+
* column counterpart of `ComponentProps`.
|
|
46
40
|
*/
|
|
47
41
|
export interface ColumnProps {
|
|
48
42
|
}
|
|
49
|
-
/**
|
|
50
|
-
* Resolves a column `type` to its props: consumer augmentations (`ColumnProps`)
|
|
51
|
-
* first, then the generated built-ins, then a loose bag.
|
|
52
|
-
*/
|
|
53
43
|
export type ColumnPropsOf<TType extends string> = ResolveProps<ColumnProps, ColumnPropsMap, TType, Record<string, unknown> | undefined>;
|