@wix/bex-core 2.333.0 → 2.337.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/cjs/assets/locale/messages_ar.json +10 -2
- package/dist/cjs/assets/locale/messages_bg.json +10 -2
- package/dist/cjs/assets/locale/messages_ca.json +10 -2
- package/dist/cjs/assets/locale/messages_cs.json +8 -0
- package/dist/cjs/assets/locale/messages_da.json +8 -0
- package/dist/cjs/assets/locale/messages_de.json +8 -0
- package/dist/cjs/assets/locale/messages_el.json +10 -2
- package/dist/cjs/assets/locale/messages_en.json +10 -2
- package/dist/cjs/assets/locale/messages_es.json +8 -0
- package/dist/cjs/assets/locale/messages_fi.json +10 -2
- package/dist/cjs/assets/locale/messages_fr.json +8 -0
- package/dist/cjs/assets/locale/messages_he.json +10 -2
- package/dist/cjs/assets/locale/messages_hi.json +8 -0
- package/dist/cjs/assets/locale/messages_hu.json +10 -2
- package/dist/cjs/assets/locale/messages_id.json +8 -0
- package/dist/cjs/assets/locale/messages_it.json +8 -0
- package/dist/cjs/assets/locale/messages_ja.json +8 -0
- package/dist/cjs/assets/locale/messages_ko.json +8 -0
- package/dist/cjs/assets/locale/messages_lt.json +10 -2
- package/dist/cjs/assets/locale/messages_ms.json +10 -2
- package/dist/cjs/assets/locale/messages_nl.json +8 -0
- package/dist/cjs/assets/locale/messages_no.json +8 -0
- package/dist/cjs/assets/locale/messages_pl.json +8 -0
- package/dist/cjs/assets/locale/messages_pt.json +8 -0
- package/dist/cjs/assets/locale/messages_ro.json +10 -2
- package/dist/cjs/assets/locale/messages_ru.json +8 -0
- package/dist/cjs/assets/locale/messages_sk.json +10 -2
- package/dist/cjs/assets/locale/messages_sl.json +10 -2
- package/dist/cjs/assets/locale/messages_sv.json +8 -0
- package/dist/cjs/assets/locale/messages_th.json +8 -0
- package/dist/cjs/assets/locale/messages_tl.json +10 -2
- package/dist/cjs/assets/locale/messages_tr.json +8 -0
- package/dist/cjs/assets/locale/messages_uk.json +8 -0
- package/dist/cjs/assets/locale/messages_vi.json +8 -0
- package/dist/cjs/assets/locale/messages_zh.json +8 -0
- package/dist/cjs/assets/locale/version_file +1 -1
- package/dist/cjs/hooks/index.js +6 -0
- package/dist/cjs/hooks/index.js.map +1 -1
- package/dist/cjs/hooks/useImport.js +4 -0
- package/dist/cjs/hooks/useImport.js.map +1 -1
- package/dist/cjs/hooks/useSchemaSource.js +11 -0
- package/dist/cjs/hooks/useSchemaSource.js.map +1 -0
- package/dist/cjs/index.js +11 -2
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/services/translations.js.map +1 -1
- package/dist/cjs/state/ImportState/ImportState.js +104 -15
- package/dist/cjs/state/ImportState/ImportState.js.map +1 -1
- package/dist/cjs/state/ImportState/__tests__/ImportState.engine.spec.js +32 -3
- package/dist/cjs/state/ImportState/__tests__/ImportState.engine.spec.js.map +1 -1
- package/dist/cjs/state/ImportState/__tests__/buildImportConfig.spec.js +156 -0
- package/dist/cjs/state/ImportState/__tests__/buildImportConfig.spec.js.map +1 -0
- package/dist/cjs/state/ImportState/detectFieldType.js +20 -2
- package/dist/cjs/state/ImportState/detectFieldType.js.map +1 -1
- package/dist/cjs/state/SourceState.js +150 -0
- package/dist/cjs/state/SourceState.js.map +1 -0
- package/dist/cjs/state/index.js +7 -0
- package/dist/cjs/state/index.js.map +1 -1
- package/dist/cjs/testkit/createInMemorySchemaSource.js +14 -8
- package/dist/cjs/testkit/createInMemorySchemaSource.js.map +1 -1
- package/dist/cjs/testkit/hubJobImportMocks.js +14 -4
- package/dist/cjs/testkit/hubJobImportMocks.js.map +1 -1
- package/dist/cjs/types/Field.js.map +1 -1
- package/dist/cjs/types/FieldTypeDefinition.js +79 -0
- package/dist/cjs/types/FieldTypeDefinition.js.map +1 -0
- package/dist/cjs/types/FieldsSource.js.map +1 -1
- package/dist/cjs/types/Schema.js.map +1 -1
- package/dist/cjs/types/SchemaSource.js +41 -20
- package/dist/cjs/types/SchemaSource.js.map +1 -1
- package/dist/cjs/types/__tests__/defineSchemaSource.fieldTypes.spec.js +78 -0
- package/dist/cjs/types/__tests__/defineSchemaSource.fieldTypes.spec.js.map +1 -0
- package/dist/esm/assets/locale/messages_ar.json +10 -2
- package/dist/esm/assets/locale/messages_bg.json +10 -2
- package/dist/esm/assets/locale/messages_ca.json +10 -2
- package/dist/esm/assets/locale/messages_cs.json +8 -0
- package/dist/esm/assets/locale/messages_da.json +8 -0
- package/dist/esm/assets/locale/messages_de.json +8 -0
- package/dist/esm/assets/locale/messages_el.json +10 -2
- package/dist/esm/assets/locale/messages_en.json +10 -2
- package/dist/esm/assets/locale/messages_es.json +8 -0
- package/dist/esm/assets/locale/messages_fi.json +10 -2
- package/dist/esm/assets/locale/messages_fr.json +8 -0
- package/dist/esm/assets/locale/messages_he.json +10 -2
- package/dist/esm/assets/locale/messages_hi.json +8 -0
- package/dist/esm/assets/locale/messages_hu.json +10 -2
- package/dist/esm/assets/locale/messages_id.json +8 -0
- package/dist/esm/assets/locale/messages_it.json +8 -0
- package/dist/esm/assets/locale/messages_ja.json +8 -0
- package/dist/esm/assets/locale/messages_ko.json +8 -0
- package/dist/esm/assets/locale/messages_lt.json +10 -2
- package/dist/esm/assets/locale/messages_ms.json +10 -2
- package/dist/esm/assets/locale/messages_nl.json +8 -0
- package/dist/esm/assets/locale/messages_no.json +8 -0
- package/dist/esm/assets/locale/messages_pl.json +8 -0
- package/dist/esm/assets/locale/messages_pt.json +8 -0
- package/dist/esm/assets/locale/messages_ro.json +10 -2
- package/dist/esm/assets/locale/messages_ru.json +8 -0
- package/dist/esm/assets/locale/messages_sk.json +10 -2
- package/dist/esm/assets/locale/messages_sl.json +10 -2
- package/dist/esm/assets/locale/messages_sv.json +8 -0
- package/dist/esm/assets/locale/messages_th.json +8 -0
- package/dist/esm/assets/locale/messages_tl.json +10 -2
- package/dist/esm/assets/locale/messages_tr.json +8 -0
- package/dist/esm/assets/locale/messages_uk.json +8 -0
- package/dist/esm/assets/locale/messages_vi.json +8 -0
- package/dist/esm/assets/locale/messages_zh.json +8 -0
- package/dist/esm/assets/locale/version_file +1 -1
- package/dist/esm/hooks/index.js +1 -0
- package/dist/esm/hooks/index.js.map +1 -1
- package/dist/esm/hooks/useImport.js +3 -1
- package/dist/esm/hooks/useImport.js.map +1 -1
- package/dist/esm/hooks/useSchemaSource.js +7 -0
- package/dist/esm/hooks/useSchemaSource.js.map +1 -0
- package/dist/esm/index.js +2 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/state/ImportState/ImportState.js +67 -7
- package/dist/esm/state/ImportState/ImportState.js.map +1 -1
- package/dist/esm/state/ImportState/__tests__/ImportState.engine.spec.js +32 -4
- package/dist/esm/state/ImportState/__tests__/ImportState.engine.spec.js.map +1 -1
- package/dist/esm/state/ImportState/__tests__/buildImportConfig.spec.js +100 -0
- package/dist/esm/state/ImportState/__tests__/buildImportConfig.spec.js.map +1 -0
- package/dist/esm/state/ImportState/detectFieldType.js +15 -15
- package/dist/esm/state/ImportState/detectFieldType.js.map +1 -1
- package/dist/esm/state/SourceState.js +131 -0
- package/dist/esm/state/SourceState.js.map +1 -0
- package/dist/esm/state/index.js +1 -0
- package/dist/esm/state/index.js.map +1 -1
- package/dist/esm/testkit/createInMemorySchemaSource.js +9 -7
- package/dist/esm/testkit/createInMemorySchemaSource.js.map +1 -1
- package/dist/esm/testkit/hubJobImportMocks.js +14 -4
- package/dist/esm/testkit/hubJobImportMocks.js.map +1 -1
- package/dist/esm/types/FieldTypeDefinition.js +16 -0
- package/dist/esm/types/FieldTypeDefinition.js.map +1 -0
- package/dist/esm/types/SchemaSource.js +33 -14
- package/dist/esm/types/SchemaSource.js.map +1 -1
- package/dist/esm/types/__tests__/defineSchemaSource.fieldTypes.spec.js +51 -0
- package/dist/esm/types/__tests__/defineSchemaSource.fieldTypes.spec.js.map +1 -0
- package/dist/types/hooks/index.d.ts +1 -0
- package/dist/types/hooks/index.d.ts.map +1 -1
- package/dist/types/hooks/useImport.d.ts +9 -3
- package/dist/types/hooks/useImport.d.ts.map +1 -1
- package/dist/types/hooks/useSchemaSource.d.ts +4 -0
- package/dist/types/hooks/useSchemaSource.d.ts.map +1 -0
- package/dist/types/index.d.ts +4 -3
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/services/translations.d.ts +1 -1
- package/dist/types/services/translations.d.ts.map +1 -1
- package/dist/types/state/ImportState/ImportState.d.ts +53 -14
- package/dist/types/state/ImportState/ImportState.d.ts.map +1 -1
- package/dist/types/state/ImportState/__tests__/buildImportConfig.spec.d.ts +2 -0
- package/dist/types/state/ImportState/__tests__/buildImportConfig.spec.d.ts.map +1 -0
- package/dist/types/state/ImportState/detectFieldType.d.ts +3 -0
- package/dist/types/state/ImportState/detectFieldType.d.ts.map +1 -1
- package/dist/types/state/SourceState.d.ts +39 -0
- package/dist/types/state/SourceState.d.ts.map +1 -0
- package/dist/types/state/index.d.ts +1 -0
- package/dist/types/state/index.d.ts.map +1 -1
- package/dist/types/testkit/WixPatternsContainer.driver.d.ts +2 -0
- package/dist/types/testkit/WixPatternsContainer.driver.d.ts.map +1 -1
- package/dist/types/testkit/createInMemorySchemaSource.d.ts +12 -7
- package/dist/types/testkit/createInMemorySchemaSource.d.ts.map +1 -1
- package/dist/types/testkit/hubJobImportMocks.d.ts +8 -0
- package/dist/types/testkit/hubJobImportMocks.d.ts.map +1 -1
- package/dist/types/types/Field.d.ts +6 -1
- package/dist/types/types/Field.d.ts.map +1 -1
- package/dist/types/types/FieldTypeDefinition.d.ts +253 -0
- package/dist/types/types/FieldTypeDefinition.d.ts.map +1 -0
- package/dist/types/types/FieldsSource.d.ts +29 -1
- package/dist/types/types/FieldsSource.d.ts.map +1 -1
- package/dist/types/types/Schema.d.ts +10 -6
- package/dist/types/types/Schema.d.ts.map +1 -1
- package/dist/types/types/SchemaSource.d.ts +44 -10
- package/dist/types/types/SchemaSource.d.ts.map +1 -1
- package/dist/types/types/__tests__/defineSchemaSource.fieldTypes.spec.d.ts +2 -0
- package/dist/types/types/__tests__/defineSchemaSource.fieldTypes.spec.d.ts.map +1 -0
- package/package.json +4 -4
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
exports.__esModule = true;
|
|
4
|
+
exports.defineFieldType = defineFieldType;
|
|
5
|
+
exports.isFilterTypeConfig = isFilterTypeConfig;
|
|
6
|
+
exports.resolveFieldTypeDefinition = resolveFieldTypeDefinition;
|
|
7
|
+
/**
|
|
8
|
+
* Props passed to a cell type's optional `EditWrapper`. The table mounts the
|
|
9
|
+
* wrapper around the cell content and keeps it mounted across the edit↔view
|
|
10
|
+
* transition, so the wrapper can own behavior that must outlive the inline
|
|
11
|
+
* editor (e.g. a reference cell navigating to an overlay and refreshing on
|
|
12
|
+
* return). The wrapper hands anything the editor needs down via its own context.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* The editable-cell slot of a field type definition: how a cell of that type
|
|
17
|
+
* renders, edits, and moves through the clipboard. The definition's key
|
|
18
|
+
* identifies the type and the definition's `value` owns validation, so the
|
|
19
|
+
* slot carries neither.
|
|
20
|
+
*
|
|
21
|
+
* Members that take `V` use method syntax so a definition typed with a
|
|
22
|
+
* concrete value type stays assignable where a loosely typed definition is
|
|
23
|
+
* expected (see `FieldTypeDefinition`).
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
/** The props the filter builder passes to a definition's toolbar filter
|
|
27
|
+
* component — the same contract the built-in filter elements receive. */
|
|
28
|
+
|
|
29
|
+
/** The filter slot of a field type definition: the filter state registered on
|
|
30
|
+
* the collection query and the toolbar element that renders it. */
|
|
31
|
+
|
|
32
|
+
/** Narrows a definition's filter slot to an active filter config. */
|
|
33
|
+
function isFilterTypeConfig(filter) {
|
|
34
|
+
return 'createFilter' in filter;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* The read-only table slot of a field type definition: how a cell of that
|
|
39
|
+
* type renders in the table, and the column's layout. Independent of
|
|
40
|
+
* `editableTable` — neither slot falls back to the other.
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
/** An extra menu item a field type definition adds to a field's actions menu. */
|
|
44
|
+
|
|
45
|
+
/** The actions slot of a field type definition: extra items for the field's "more actions" menu. */
|
|
46
|
+
|
|
47
|
+
/** Display metadata for a field type: menu label and type icons. */
|
|
48
|
+
|
|
49
|
+
/** Value semantics of a field type, independent of any rendering surface.
|
|
50
|
+
* Members use method syntax so a definition typed with a concrete value type
|
|
51
|
+
* stays assignable where a loosely typed definition is expected. */
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* A consumer-defined field type. Defined once on the fields source; every
|
|
55
|
+
* entry point that renders the field resolves its slot from here. `V` is the
|
|
56
|
+
* field's value type — `defineFieldType` infers it, and it keeps all the
|
|
57
|
+
* slots consistent with each other.
|
|
58
|
+
*
|
|
59
|
+
* Sources hold definitions of mixed value types in one
|
|
60
|
+
* `FieldTypeDefinition[]` (= `FieldTypeDefinition<unknown>[]`) array. That
|
|
61
|
+
* works because every member that takes `V` is declared with method syntax,
|
|
62
|
+
* which TypeScript checks bivariantly — so `FieldTypeDefinition<number>` is
|
|
63
|
+
* assignable to `FieldTypeDefinition<unknown>` without casts.
|
|
64
|
+
*/
|
|
65
|
+
|
|
66
|
+
/** Identity factory: infers `V` and keeps the definition's slots type-checked. */
|
|
67
|
+
function defineFieldType(definition) {
|
|
68
|
+
return definition;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** Resolves the definition a CUSTOM field references on its source. */
|
|
72
|
+
function resolveFieldTypeDefinition(source, field) {
|
|
73
|
+
var _source$fieldTypes;
|
|
74
|
+
if (field.type !== 'CUSTOM' || !field.customType) {
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
return (_source$fieldTypes = source.fieldTypes) == null ? void 0 : _source$fieldTypes.find(def => def.type === field.customType);
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=FieldTypeDefinition.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["isFilterTypeConfig","filter","defineFieldType","definition","resolveFieldTypeDefinition","source","field","_source$fieldTypes","type","customType","undefined","fieldTypes","find","def"],"sources":["../../../src/types/FieldTypeDefinition.ts"],"sourcesContent":["import type {\n ComponentType,\n MutableRefObject,\n ReactElement,\n ReactNode,\n} from 'react';\nimport type { Field } from './Field';\nimport type { Filter } from '../model/filter';\nimport type { FieldsSource } from './FieldsSource';\n\nexport type ValidationRule =\n | { type: 'required'; message: string }\n | { type: 'min' | 'max'; value: number; message: string }\n | { type: 'minLength' | 'maxLength'; value: number; message: string }\n | { type: 'pattern'; value: RegExp; message: string }\n | { type: 'custom'; validate: (value: unknown) => boolean; message: string }\n | {\n type: 'specificValues';\n values: { id: string; value: string }[];\n message: string;\n };\n\nexport interface Focusable {\n focus: () => void;\n}\n\nexport type EditTrigger =\n | { kind: 'type'; key: string }\n | 'enter'\n | 'click'\n | 'doubleClick';\n\nexport interface CellViewProps<V> {\n value: V;\n typeConfig?: unknown;\n validation?: ValidationRule[];\n /** Stable id of the column. Cell components can use it to derive unique DOM ids. */\n columnId: string;\n /** Stable key of the row. Cell components can use it to derive unique DOM ids. */\n rowKey: string;\n}\n\nexport interface CellEditProps<V> {\n value: V;\n // Method syntax keeps CellEditProps covariant in V (see FieldTypeDefinition).\n onChange(value: V): void;\n onCommit: () => void;\n onCancel: () => void;\n /**\n * Signals that the cell is starting an editing operation that will move focus\n * outside the table (e.g., opening a media manager or a modal). Calling this\n * sets isEditing=true so the table does not clear cell focus while the\n * external UI is open. Pair with onCommit (after the operation succeeds)\n * or onCancel (if the user dismisses without a value change).\n */\n onStartEdit?: () => void;\n /** Ref to the focusable input element. Used for type-to-edit (focusing the input when user starts typing on a focused cell). */\n inputRef?: MutableRefObject<Focusable | undefined | null>;\n typeConfig?: unknown;\n /** How edit mode was triggered. Edit components can use this to customize behavior (e.g., date picker auto-opens on 'type'). */\n editTrigger?: EditTrigger | null;\n /** Column-level validation rules. Edit components can derive UI behavior (e.g., maxLength blocking/tooltip) from these. */\n validation?: ValidationRule[];\n /** Stable id of the column. Cell components can use it to derive unique DOM ids. */\n columnId: string;\n /** Stable key of the row. Cell components can use it to derive unique DOM ids. */\n rowKey: string;\n}\n\n/**\n * Props passed to a cell type's optional `EditWrapper`. The table mounts the\n * wrapper around the cell content and keeps it mounted across the edit↔view\n * transition, so the wrapper can own behavior that must outlive the inline\n * editor (e.g. a reference cell navigating to an overlay and refreshing on\n * return). The wrapper hands anything the editor needs down via its own context.\n */\nexport interface CellEditWrapperProps {\n /** The column's typeConfig (same value handed to the cell's Edit/View). */\n typeConfig?: unknown;\n /** Stable id of the column. */\n columnId: string;\n /** Stable key of the row. */\n rowKey: string;\n /** The cell content (the Edit or View component) to render inside the wrapper. */\n children: ReactNode;\n}\n\n/**\n * The editable-cell slot of a field type definition: how a cell of that type\n * renders, edits, and moves through the clipboard. The definition's key\n * identifies the type and the definition's `value` owns validation, so the\n * slot carries neither.\n *\n * Members that take `V` use method syntax so a definition typed with a\n * concrete value type stays assignable where a loosely typed definition is\n * expected (see `FieldTypeDefinition`).\n */\nexport interface EditableCellConfig<V> {\n /** Render cell in view mode (read-only display). */\n ViewComponent(props: CellViewProps<V>): ReactElement | null;\n /** Render cell in edit mode (inline editor). Optional — omit for view-only cells. */\n EditComponent?(props: CellEditProps<V>): ReactElement | null;\n /** Serialize value to clipboard string. */\n serialize?(value: V): string;\n /** Deserialize clipboard string to value. */\n deserialize?(raw: string): V;\n /** Can this cell type be edited? (default: true) */\n editable?: boolean;\n /** Can this cell type be cleared with Delete key? (default: true) */\n clearable?: boolean;\n /** Toggle value on single click (e.g., boolean checkbox). Skips focus→edit flow. */\n toggleValue?(value: V): V;\n /** Enter edit mode on single click (e.g., image cell with no value). */\n editOnClick?(value: V): boolean;\n /** Show the EditComponent when the cell is focused, without entering edit mode.\n * Keyboard navigation remains active. Similar to toggleValue but without toggling. */\n showEditWhenFocused?: boolean;\n /** Optional wrapper component the cell type defines to own behavior that must\n * outlive the inline editor. Mounted around the cell content and kept mounted\n * across the edit↔view transition. */\n EditWrapper?: ComponentType<CellEditWrapperProps>;\n /** Cell content can grow past row height when focused. Only applies to\n * showEditWhenFocused cells. */\n growable?: boolean;\n /** Called on type-to-edit. Return object with cleared value and/or prevent flag.\n * Return undefined to block the key. Return {} to enter edit mode without changing the value. */\n onTypeToEdit?(params: {\n key: string;\n validation?: ValidationRule[];\n }): { value?: V } | undefined;\n /** Optional hook to normalize the committed value (e.g. auto-prepend https://).\n * Called before the edit commits; the value is written back before committing. */\n normalizeOnCommit?(value: V): V;\n /** When true, type-to-edit flushes the edit-mode render synchronously and\n * focuses the input within the same keydown event, then lets the browser's\n * default action deliver the keystroke to the now-focused input naturally.\n * Use for cells that wrap a controlled input whose value can't be seeded via props. */\n nativeTypeToEdit?: boolean;\n}\n\n/** The props the filter builder passes to a definition's toolbar filter\n * component — the same contract the built-in filter elements receive. */\nexport interface FilterTypeComponentProps<V = any> {\n filter: Filter<V>;\n toolbarItemProps?: { label?: ReactNode };\n toolbarTagProps?: { label?: string };\n accordionItemProps?: { label?: string };\n}\n\n/** The filter slot of a field type definition: the filter state registered on\n * the collection query and the toolbar element that renders it. */\nexport interface FilterTypeConfig {\n createFilter: (field: Field) => Filter<any>;\n Component: ComponentType<FilterTypeComponentProps>;\n}\n\n/** Narrows a definition's filter slot to an active filter config. */\nexport function isFilterTypeConfig(\n filter: FieldTypeDefinition['filter'],\n): filter is FilterTypeConfig {\n return 'createFilter' in filter;\n}\n\n/**\n * The read-only table slot of a field type definition: how a cell of that\n * type renders in the table, and the column's layout. Independent of\n * `editableTable` — neither slot falls back to the other.\n */\nexport interface TableCellConfig<V> {\n /** Render the cell. Method syntax keeps the definition assignable to\n * `FieldTypeDefinition<unknown>` (see FieldTypeDefinition). */\n CellComponent(props: { value: V }): ReactElement | null;\n /** Column width. Required — custom types get no built-in layout default. */\n width: string;\n /** Default: 'start'. */\n align?: 'start' | 'center' | 'end';\n}\n\n/** An extra menu item a field type definition adds to a field's actions menu. */\nexport interface FieldTypeActionItem {\n key: string;\n label: string;\n icon?: ReactNode;\n skin?: 'destructive';\n onClick: (field: Field) => void;\n /** Default: visible. */\n visible?: (field: Field) => boolean;\n /** Returning a string disables the item and shows the tooltip. */\n disabledTooltip?: (field: Field) => string | undefined;\n}\n\n/** The actions slot of a field type definition: extra items for the field's \"more actions\" menu. */\nexport interface FieldActionsConfig {\n items?: FieldTypeActionItem[];\n}\n\n/** Display metadata for a field type: menu label and type icons. */\nexport interface FieldTypeDisplay {\n label: string;\n icons: {\n Small: ComponentType;\n Medium: ComponentType;\n };\n}\n\n/** Value semantics of a field type, independent of any rendering surface.\n * Members use method syntax so a definition typed with a concrete value type\n * stays assignable where a loosely typed definition is expected. */\nexport interface FieldValueBehavior<V> {\n defaultValue?: V;\n isEmpty?(value: V): boolean;\n /** Returns an error message, or null when the value is valid. Every surface\n * that validates a field of this type runs this. */\n validate?(value: V, rules?: ValidationRule[]): string | null;\n}\n\nexport interface FieldCapabilities {\n sortable: boolean;\n}\n\n/**\n * A consumer-defined field type. Defined once on the fields source; every\n * entry point that renders the field resolves its slot from here. `V` is the\n * field's value type — `defineFieldType` infers it, and it keeps all the\n * slots consistent with each other.\n *\n * Sources hold definitions of mixed value types in one\n * `FieldTypeDefinition[]` (= `FieldTypeDefinition<unknown>[]`) array. That\n * works because every member that takes `V` is declared with method syntax,\n * which TypeScript checks bivariantly — so `FieldTypeDefinition<number>` is\n * assignable to `FieldTypeDefinition<unknown>` without casts.\n */\nexport interface FieldTypeDefinition<V = unknown> {\n /** Unique key for the type. A built-in type uses its `PatternsFieldType`; a\n * consumer-defined type uses the string its fields reference via `customType`. */\n type: string;\n display: FieldTypeDisplay;\n /** Filter behavior, or an explicit opt-out — never silently absent. */\n filter: FilterTypeConfig | { filterable: false };\n value?: FieldValueBehavior<V>;\n capabilities?: FieldCapabilities;\n /** Absent ⇒ the field renders with the default cell in the read-only table. */\n table?: TableCellConfig<V>;\n /** Absent ⇒ the field renders as a read-only cell in editable surfaces. */\n editableTable?: EditableCellConfig<V>;\n /** Extra items for the field's \"more actions\" menu. */\n actions?: FieldActionsConfig;\n}\n\n/** Identity factory: infers `V` and keeps the definition's slots type-checked. */\nexport function defineFieldType<V>(\n definition: FieldTypeDefinition<V>,\n): FieldTypeDefinition<V> {\n return definition;\n}\n\n/** Resolves the definition a CUSTOM field references on its source. */\nexport function resolveFieldTypeDefinition(\n source: Pick<FieldsSource, 'fieldTypes'>,\n field: Field,\n) {\n if (field.type !== 'CUSTOM' || !field.customType) {\n return undefined;\n }\n return source.fieldTypes?.find((def) => def.type === field.customType);\n}\n"],"mappings":";;;;;;AAqEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAYA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AA4CA;AACA;;AAQA;AACA;;AAMA;AACO,SAASA,kBAAkBA,CAChCC,MAAqC,EACT;EAC5B,OAAO,cAAc,IAAIA,MAAM;AACjC;;AAEA;AACA;AACA;AACA;AACA;;AAWA;;AAaA;;AAKA;;AASA;AACA;AACA;;AAaA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAkBA;AACO,SAASC,eAAeA,CAC7BC,UAAkC,EACV;EACxB,OAAOA,UAAU;AACnB;;AAEA;AACO,SAASC,0BAA0BA,CACxCC,MAAwC,EACxCC,KAAY,EACZ;EAAA,IAAAC,kBAAA;EACA,IAAID,KAAK,CAACE,IAAI,KAAK,QAAQ,IAAI,CAACF,KAAK,CAACG,UAAU,EAAE;IAChD,OAAOC,SAAS;EAClB;EACA,QAAAH,kBAAA,GAAOF,MAAM,CAACM,UAAU,qBAAjBJ,kBAAA,CAAmBK,IAAI,CAAEC,GAAG,IAAKA,GAAG,CAACL,IAAI,KAAKF,KAAK,CAACG,UAAU,CAAC;AACxE","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["../../../src/types/FieldsSource.ts"],"sourcesContent":["import type { Field, PatternsFieldType } from './Field';\nimport type { FieldActions, Schema } from './Schema';\n\n/** A field the source has archived. Sources without archiving omit `archive`. */\nexport interface ArchivedFieldItem {\n id: string;\n label: string;\n isPii?: boolean;\n}\n\n/** A field type a source allows creating, with display metadata for the modal. */\nexport interface FieldTypeOption {\n /** Stored on the draft; the source maps it back to its native type. */\n id: string;\n label: string;\n namePlaceholder?: string;\n /** Drives the type icon in the modal. */\n patternsType: PatternsFieldType;\n}\n\n/** Read/write permission defaults a source supports, per audience. */\nexport interface FieldPermissions {\n installedApps?: {\n hide?: boolean;\n defaultRead?: boolean;\n defaultWrite?: boolean;\n };\n siteVisitors?: {\n hide?: boolean;\n defaultRead?: boolean;\n defaultWrite?: boolean;\n };\n}\n\n/** The values the add/edit field modal collects, source-neutral. */\nexport interface FieldDraft {\n type?: string;\n key: string;\n name: string;\n readApps: boolean;\n readUsers: boolean;\n writeApps: boolean;\n writeUsers: boolean;\n containsPii: boolean;\n}\n\n/** Add/edit/delete capability a source exposes. Present ⇒ field management UI shows. */\nexport interface FieldManagement {\n /** False ⇒ the add-field CTA is hidden entirely. */\n canAddFields: boolean;\n /** True ⇒ the add-field CTA renders but is disabled. */\n addFieldDisabled: boolean;\n /** Hint text shown beneath the add-field CTA while it is disabled. */\n addFieldDisabledHint?: string;\n canEditField(field: Field): boolean;\n /** `origin` is the UI surface the delete was triggered from; used for BI. */\n deleteField(fieldId: string, origin: string): Promise<void>;\n\n /** Field types the source allows creating, shown in the add/edit modal. */\n creatableFieldTypes: FieldTypeOption[];\n /** Existing field keys, used by the add modal to reject duplicates. */\n existingFieldKeys: string[];\n /** True when no more fields can be added because a limit is reached. */\n maxReached?: boolean;\n /** Permission defaults; absent ⇒ the modal hides the permissions section. */\n permissions?: FieldPermissions;\n /**
|
|
1
|
+
{"version":3,"names":[],"sources":["../../../src/types/FieldsSource.ts"],"sourcesContent":["import type { Field, PatternsFieldType } from './Field';\nimport type { FieldActions, Schema } from './Schema';\nimport type { FieldTypeDefinition } from './FieldTypeDefinition';\n\n/** A field the source has archived. Sources without archiving omit `archive`. */\nexport interface ArchivedFieldItem {\n id: string;\n label: string;\n isPii?: boolean;\n}\n\n/** A field type a source allows creating, with display metadata for the modal. */\nexport interface FieldTypeOption {\n /** Stored on the draft; the source maps it back to its native type. */\n id: string;\n label: string;\n namePlaceholder?: string;\n subtitle?: string;\n /** Group heading in the type list; types sharing a heading form one group. */\n group?: string;\n /** Drives the type icon in the modal. */\n patternsType: PatternsFieldType;\n}\n\n/** Read/write permission defaults a source supports, per audience. */\nexport interface FieldPermissions {\n installedApps?: {\n hide?: boolean;\n defaultRead?: boolean;\n defaultWrite?: boolean;\n };\n siteVisitors?: {\n hide?: boolean;\n defaultRead?: boolean;\n defaultWrite?: boolean;\n };\n}\n\n/** The values the add/edit field modal collects, source-neutral. */\nexport interface FieldDraft {\n type?: string;\n key: string;\n name: string;\n readApps: boolean;\n readUsers: boolean;\n writeApps: boolean;\n writeUsers: boolean;\n containsPii: boolean;\n}\n\n/** The add-modal subtitle: a line of text, an optional second note line, and an\n * optional \"learn more\" link. */\nexport interface FieldModalSubtitle {\n text: string;\n note?: string;\n learnMore?: { label: string; href: string };\n}\n\n/** Title and subtitle a source supplies for the add/edit field modal. */\nexport interface FieldModalText {\n addTitle: string;\n editTitle: string;\n /** Subtitle for the add modal; omit for none. */\n addSubtitle?: FieldModalSubtitle;\n}\n\n/** Add/edit/delete capability a source exposes. Present ⇒ field management UI shows. */\nexport interface FieldManagement {\n /** False ⇒ the add-field CTA is hidden entirely. */\n canAddFields: boolean;\n /** True ⇒ the add-field CTA renders but is disabled. */\n addFieldDisabled: boolean;\n /** Hint text shown beneath the add-field CTA while it is disabled. */\n addFieldDisabledHint?: string;\n canEditField(field: Field): boolean;\n /** `origin` is the UI surface the delete was triggered from; used for BI. */\n deleteField(fieldId: string, origin: string): Promise<void>;\n\n /** Field types the source allows creating, shown in the add/edit modal. */\n creatableFieldTypes: FieldTypeOption[];\n /** Existing field keys, used by the add modal to reject duplicates. */\n existingFieldKeys: string[];\n /** True when no more fields can be added because a limit is reached. */\n maxReached?: boolean;\n /** Permission defaults; absent ⇒ the modal hides the permissions section. */\n permissions?: FieldPermissions;\n /** Source-wide default for whether a field type can be marked PII. A field\n * type overrides it by declaring `form.pii` in its definition. */\n supportsPii?: boolean;\n /** Title and subtitle for the add/edit field modal. */\n fieldModalText: FieldModalText;\n addField(draft: FieldDraft): Promise<void>;\n editField(fieldId: string, draft: FieldDraft): Promise<void>;\n /** Current values for an existing field, to prefill the edit modal. */\n getFieldDraft(fieldId: string): FieldDraft | undefined;\n}\n\n/** Archiving capability a source exposes. Present ⇒ archive/restore UI shows. */\nexport interface FieldArchive {\n items: ArchivedFieldItem[];\n shouldDisplay: boolean;\n /** Whether the archived-items panel is currently open. */\n isOpen: boolean;\n openPanel(): void;\n closePanel(): void;\n /** `origin` is the UI surface the action was triggered from; used for BI. */\n archiveField(fieldId: string, origin: string): Promise<void>;\n restoreField(fieldId: string, origin: string): Promise<void>;\n /** Display name for a field, for the confirm-dialog copy. */\n fieldName(fieldId: string): string;\n}\n\n/**\n * The source-neutral fields data a collection reads, implemented by each source\n * adapter. Rendering — field modals, filter elements — is not here; it lives in\n * the collection-page layer.\n */\nexport interface FieldsSource {\n /** Loads the fields (schema/data). The collection runs this once, tracks its\n * status, and shows a retry toast on failure. */\n load(): Promise<void>;\n\n fields: Field[];\n filterableFields: Field[];\n /** The fields the manage-fields panel lists — the source's editable fields. */\n manageableFields: Field[];\n /** Column id for a field. Sources that group fields prefix the group; flat sources use the field key. */\n columnIdForField(field: Field): string;\n /** WQL field path for a filter. Sources that group fields prefix the group; flat sources use the field key. */\n queryFieldId(field: Field): string;\n /** The value to display for a field on a row. */\n getCellValue(row: unknown, field: Field): unknown;\n /** Writes a new value for a field on a row, returning the updated row. Present when cells can be edited in place. */\n setCellValue?(row: unknown, field: Field, value: unknown): unknown;\n\n /** Replaces the source's fields with a freshly-returned map, updating the\n * columns with no refetch. Present when the source holds its fields in a\n * mergeable state (e.g. a loaded schema); used after an import creates fields. */\n mergeFields?(fields: Schema['fields']): void;\n\n /** Field-type definitions the source supports. Built-in types are keyed by\n * their `PatternsFieldType`; consumer-defined types are keyed by the string a\n * field references via `customType`. */\n fieldTypes?: FieldTypeDefinition[];\n\n /** Present when fields can be added/edited/deleted. */\n fieldManagement?: FieldManagement;\n\n /** The collection's field-mutation actions (delete/makePrimary/duplicate/…),\n * driving the shared FieldActions menu. Absent ⇒ no per-field action menu. */\n fieldActions?: FieldActions;\n\n /** Present when the source supports archiving fields. */\n archive?: FieldArchive;\n\n /** Present when fields are grouped. Absent ⇒ flat list. */\n groups?: {\n all: string[];\n fieldsForGroup(group: string): Field[];\n };\n}\n"],"mappings":"","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["../../../src/types/Schema.ts"],"sourcesContent":["import type { Field } from './Field';\nimport type { FiltersMap, OptionalFiltersMap } from '../model';\nimport type {\n OffsetQuery,\n OffsetQueryResult,\n CursorQuery,\n CursorQueryResult,\n FetchTotalFn,\n} from '../hooks/paginationModeConfig';\n\n/** Field-management permissions. Absent when the schema's fields cannot be edited. */\nexport interface SchemaPermissions {\n createField: boolean;\n updateField: boolean;\n deleteField: boolean;\n}\n\n/** Item-level CRUD permissions. */\nexport interface ItemPermissions {\n createItem: boolean;\n updateItem: boolean;\n deleteItem: boolean;\n}\n\n/**\n * A source-neutral description of a collection — data only, no behavior.\n * Item access is in `CollectionBackend`, field mutations in `FieldActions`.\n */\nexport interface Schema {\n id: string;\n fields: Record<string, Field | undefined>;\n /** The field that best represents the entity (titles/selections). */\n displayField: string;\n /** The identifier field. */\n idField: string;\n /** Absent when the schema's fields cannot be edited. */\n schemaPermissions?: SchemaPermissions;\n itemPermissions?: ItemPermissions;\n}\n\nexport interface BackupConfig {\n create: () => Promise<{ backupId: string }>;\n waitForCompletion: (\n backupId: string,\n options?: { signal?: AbortSignal },\n ) => Promise<void>;\n cancel?: (backupId: string) => Promise<void>;\n restore?: (backupId: string) => Promise<{ restorationId: string }>;\n waitForRestoration?: (\n restorationId: string,\n options?: { signal?: AbortSignal },\n ) => Promise<void>;\n}\n\nexport interface BulkInsertError {\n rowIndex: number;\n message?: string;\n code?: string;\n}\n\nexport interface BulkInsertResult {\n succeeded?: number;\n failed?: number;\n errors?: BulkInsertError[];\n}\n\n/** Item data access shared by both pagination modes. */\nexport interface CollectionBackendBase<T = Record<string, unknown>> {\n get
|
|
1
|
+
{"version":3,"names":[],"sources":["../../../src/types/Schema.ts"],"sourcesContent":["import type { Field } from './Field';\nimport type { FiltersMap, OptionalFiltersMap } from '../model';\nimport type {\n OffsetQuery,\n OffsetQueryResult,\n CursorQuery,\n CursorQueryResult,\n FetchTotalFn,\n} from '../hooks/paginationModeConfig';\n\n/** Field-management permissions. Absent when the schema's fields cannot be edited. */\nexport interface SchemaPermissions {\n createField: boolean;\n updateField: boolean;\n deleteField: boolean;\n}\n\n/** Item-level CRUD permissions. */\nexport interface ItemPermissions {\n createItem: boolean;\n updateItem: boolean;\n deleteItem: boolean;\n}\n\n/**\n * A source-neutral description of a collection — data only, no behavior.\n * Item access is in `CollectionBackend`, field mutations in `FieldActions`.\n */\nexport interface Schema {\n id: string;\n fields: Record<string, Field | undefined>;\n /** The field that best represents the entity (titles/selections). */\n displayField: string;\n /** The identifier field. */\n idField: string;\n /** Group display order, present when fields carry a `group`. */\n groups?: string[];\n /** Absent when the schema's fields cannot be edited. */\n schemaPermissions?: SchemaPermissions;\n itemPermissions?: ItemPermissions;\n}\n\nexport interface BackupConfig {\n create: () => Promise<{ backupId: string }>;\n waitForCompletion: (\n backupId: string,\n options?: { signal?: AbortSignal },\n ) => Promise<void>;\n cancel?: (backupId: string) => Promise<void>;\n restore?: (backupId: string) => Promise<{ restorationId: string }>;\n waitForRestoration?: (\n restorationId: string,\n options?: { signal?: AbortSignal },\n ) => Promise<void>;\n}\n\nexport interface BulkInsertError {\n rowIndex: number;\n message?: string;\n code?: string;\n}\n\nexport interface BulkInsertResult {\n succeeded?: number;\n failed?: number;\n errors?: BulkInsertError[];\n}\n\n/** Item data access shared by both pagination modes. `find` (on\n * `CollectionBackend`) is the only required call — the rest are capabilities\n * a source provides when it (or its consumer) supports them. */\nexport interface CollectionBackendBase<T = Record<string, unknown>> {\n get?: (entityId: string) => Promise<T>;\n create?: (entity: Partial<T>) => Promise<T>;\n update?: (entity: T) => Promise<T>;\n delete?: (entityId: string) => Promise<void>;\n bulkDelete?: (entityIds: string[]) => Promise<void>;\n move?: (\n id: string,\n params: { moveAfterId: string | null | undefined },\n ) => Promise<void>;\n backup?: BackupConfig;\n bulkInsert?: (entities: Partial<T>[]) => Promise<BulkInsertResult>;\n}\n\n/** Per-call search scope the query layer passes to a backend's `find`. */\nexport interface FindOptions {\n searchableFieldIds?: string[];\n}\n\n/**\n * The query-layer fetch-data fns plus the optional `find` options the runtime\n * already accepts. Kept separate so the shared `OffsetFetchDataFn`/\n * `CursorFetchDataFn` used by `fetchData` stay unchanged.\n */\ntype OffsetFindFn<T, F extends FiltersMap> = (\n query: OffsetQuery<F>,\n options?: FindOptions,\n) => Promise<OffsetQueryResult<T>>;\ntype CursorFindFn<T, F extends FiltersMap> = (\n query: CursorQuery<F>,\n options?: FindOptions,\n) => Promise<CursorQueryResult<T>>;\n\n/**\n * A source's item data access. The source declares its `paginationMode`\n * (offset by default) together with the matching `find`, same as core's\n * `PaginationModeConfig`.\n */\nexport type CollectionBackend<\n T = Record<string, unknown>,\n F extends FiltersMap = OptionalFiltersMap,\n> = CollectionBackendBase<T> &\n (\n | { paginationMode?: 'offset'; find: OffsetFindFn<T, F> }\n | {\n paginationMode: 'cursor';\n find: CursorFindFn<T, F>;\n fetchTotal?: FetchTotalFn;\n }\n );\n\n/** Field-management actions. All optional — a read-only source provides none. */\nexport interface FieldActions {\n /**\n * Field-mutating actions return the collection's updated fields map so the\n * caller can merge its local state from the response, without reloading the\n * schema. (`renameField` is the exception — nothing consumes its result yet.)\n */\n addField?: (field: Field) => Promise<Schema['fields']>;\n /**\n * Adds several fields in a single mutation, each under its `field.id` key\n * (callers decide the keys up front — e.g. CSV import uploads values under\n * them), unlike `addField`, which derives a fresh key from the display name.\n */\n addFields?: (fields: Field[]) => Promise<Schema['fields']>;\n editField?: (\n fieldId: string,\n updates: Partial<Field>,\n ) => Promise<Schema['fields']>;\n deleteField?: (fieldId: string) => Promise<Schema['fields']>;\n renameField?: (fieldId: string, newName: string) => Promise<void>;\n makePrimary?: (fieldId: string) => Promise<Schema['fields']>;\n duplicateField?: (fieldId: string) => Promise<Schema['fields']>;\n duplicateFieldWithContent?: (fieldId: string) => Promise<Schema['fields']>;\n}\n\n/** Everything a source provides for a collection. */\nexport interface LoadedSchema<T = Record<string, unknown>> {\n schema: Schema;\n backend: CollectionBackend<T>;\n fieldActions?: FieldActions;\n}\n\n/**\n * Loads a collection's `LoadedSchema`. Sources that need dependencies expose a\n * factory that returns this type.\n */\nexport type SchemaLoader<\n T extends Record<string, unknown> = Record<string, unknown>,\n> = (collectionId: string) => Promise<LoadedSchema<T>>;\n"],"mappings":"","ignoreList":[]}
|
|
@@ -2,15 +2,36 @@
|
|
|
2
2
|
|
|
3
3
|
exports.__esModule = true;
|
|
4
4
|
exports.defineSchemaSource = defineSchemaSource;
|
|
5
|
+
exports.sourceFetchData = sourceFetchData;
|
|
5
6
|
/** A field type a source allows creating. Declare one entry per
|
|
6
7
|
* `patternsType` — the type is the entry's identity. */
|
|
7
8
|
|
|
8
|
-
/** Collection-query config derived from a source, ready to spread into a collection hook. */
|
|
9
|
-
|
|
10
9
|
/** What a caller passes. Only `collectionId` and `loadSchema` are required. */
|
|
11
10
|
|
|
12
11
|
/** The resolved source: defaults filled, `loadSchema` memoized. */
|
|
13
12
|
|
|
13
|
+
/** The collection fetch derived from a source: loads once, then queries the
|
|
14
|
+
* backend's `find`.
|
|
15
|
+
*
|
|
16
|
+
* Free-text search covers the columns the page is showing: the table keeps
|
|
17
|
+
* `query.columns` in sync with them, so the scope comes off the query rather
|
|
18
|
+
* than being threaded in. Falls back to the source's own `searchableFieldIds`
|
|
19
|
+
* before any columns are known (or with no table attached). */
|
|
20
|
+
function sourceFetchData(source) {
|
|
21
|
+
return async query => {
|
|
22
|
+
const {
|
|
23
|
+
backend,
|
|
24
|
+
schema
|
|
25
|
+
} = await source.loadSchema();
|
|
26
|
+
// `columns` is the visible-column list; `fields` is the projection, which a
|
|
27
|
+
// source-driven table doesn't set.
|
|
28
|
+
const visibleColumns = query.columns;
|
|
29
|
+
return backend.find(query, {
|
|
30
|
+
searchableFieldIds: visibleColumns != null && visibleColumns.length ? visibleColumns : source.searchableFieldIds(schema)
|
|
31
|
+
});
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
14
35
|
/** Fills source-neutral defaults over `input` and memoizes the load so the collection
|
|
15
36
|
* query and the table columns share a single fetch. */
|
|
16
37
|
function defineSchemaSource(input) {
|
|
@@ -18,8 +39,11 @@ function defineSchemaSource(input) {
|
|
|
18
39
|
collectionId,
|
|
19
40
|
paginationMode = 'offset',
|
|
20
41
|
creatableFieldTypes = [],
|
|
42
|
+
fieldTypes = [],
|
|
21
43
|
fieldPermissions,
|
|
22
|
-
supportsPii = false
|
|
44
|
+
supportsPii = false,
|
|
45
|
+
fieldModalText,
|
|
46
|
+
references = {}
|
|
23
47
|
} = input;
|
|
24
48
|
let loaded;
|
|
25
49
|
let schema;
|
|
@@ -51,32 +75,29 @@ function defineSchemaSource(input) {
|
|
|
51
75
|
var _s$schemaPermissions3;
|
|
52
76
|
return (((_s$schemaPermissions3 = s.schemaPermissions) == null ? void 0 : _s$schemaPermissions3.deleteField) ?? false) && !field.isSystem;
|
|
53
77
|
});
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
return backend.find(query, {
|
|
60
|
-
searchableFieldIds: searchableFieldIds(loadedSchema)
|
|
61
|
-
});
|
|
62
|
-
};
|
|
78
|
+
const getFieldValue = input.getFieldValue ?? ((item, field) => item[field.id]);
|
|
79
|
+
const setFieldValue = input.setFieldValue ?? ((item, field, value) => ({
|
|
80
|
+
...item,
|
|
81
|
+
[field.id]: value
|
|
82
|
+
}));
|
|
63
83
|
return {
|
|
64
84
|
collectionId,
|
|
65
85
|
loadSchema,
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
itemKey,
|
|
71
|
-
itemName
|
|
72
|
-
},
|
|
86
|
+
paginationMode,
|
|
87
|
+
itemKey,
|
|
88
|
+
itemName,
|
|
89
|
+
references,
|
|
73
90
|
creatableFieldTypes,
|
|
91
|
+
fieldTypes,
|
|
74
92
|
searchableFieldIds,
|
|
75
93
|
canAddFields,
|
|
76
94
|
canEditField,
|
|
77
95
|
canDeleteField,
|
|
78
96
|
fieldPermissions,
|
|
79
|
-
supportsPii
|
|
97
|
+
supportsPii,
|
|
98
|
+
fieldModalText,
|
|
99
|
+
getFieldValue,
|
|
100
|
+
setFieldValue
|
|
80
101
|
};
|
|
81
102
|
}
|
|
82
103
|
//# sourceMappingURL=SchemaSource.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["defineSchemaSource","input","collectionId","paginationMode","creatableFieldTypes","fieldPermissions","supportsPii","loaded","schema","loadSchema","then","result","catch","error","undefined","searchableFieldIds","s","displayField","itemKey","item","_schema","String","idField","itemName","_schema2","canAddFields","_s$schemaPermissions","schemaPermissions","createField","canEditField","field","_s$schemaPermissions2","updateField","isSystem","canDeleteField","_s$schemaPermissions3","deleteField","fetchData","query","backend","loadedSchema","find","collectionConfig","queryName"],"sources":["../../../src/types/SchemaSource.ts"],"sourcesContent":["import type { Field, PatternsFieldType } from './Field';\nimport type { Schema, LoadedSchema, FindOptions } from './Schema';\nimport type { FieldPermissions } from './FieldsSource';\nimport type {\n OffsetQuery,\n OffsetQueryResult,\n} from '../hooks/paginationModeConfig';\n\n/** A field type a source allows creating. Declare one entry per\n * `patternsType` — the type is the entry's identity. */\nexport interface CreatableFieldType {\n patternsType: PatternsFieldType;\n /** Custom display name. Absent ⇒ the UI's standard name for this type. */\n label?: string;\n /** Custom name-input placeholder. Absent ⇒ the UI's standard placeholder. */\n namePlaceholder?: string;\n}\n\n/** Collection-query config derived from a source, ready to spread into a collection hook. */\nexport interface SchemaCollectionConfig<T> {\n queryName: string;\n paginationMode: 'offset';\n fetchData: (query: OffsetQuery) => Promise<OffsetQueryResult<T>>;\n itemKey: (item: T) => string;\n itemName: (item: T) => string;\n}\n\n/** What a caller passes. Only `collectionId` and `loadSchema` are required. */\nexport interface SchemaSourceInput<T> {\n collectionId: string;\n loadSchema: () => Promise<LoadedSchema<T>>;\n paginationMode?: 'offset';\n /** Stable row identity. Default: `row[idField]`. */\n itemKey?: (item: T) => string;\n /** Row display label. Default: `row[displayField]`. */\n itemName?: (item: T) => string;\n /** Fields free-text search runs against. Default: `[displayField]`. */\n searchableFieldIds?: (schema: Schema) => string[];\n /** Field types the add-field modal offers. Default: none. */\n creatableFieldTypes?: CreatableFieldType[];\n /** Default: `schemaPermissions.createField`. */\n canAddFields?: (schema: Schema) => boolean;\n /** Default: `schemaPermissions.updateField && !field.isSystem`. */\n canEditField?: (field: Field, schema: Schema) => boolean;\n /** Default: `schemaPermissions.deleteField && !field.isSystem`. */\n canDeleteField?: (field: Field, schema: Schema) => boolean;\n /** Permission defaults shown in the modal. Absent ⇒ no permissions section. */\n fieldPermissions?: FieldPermissions;\n /** Default: `false`. */\n supportsPii?: boolean;\n}\n\n/** The resolved source: defaults filled, `loadSchema` memoized. */\nexport interface SchemaSource<T> {\n readonly collectionId: string;\n loadSchema: () => Promise<LoadedSchema<T>>;\n readonly collectionConfig: SchemaCollectionConfig<T>;\n readonly creatableFieldTypes: CreatableFieldType[];\n searchableFieldIds: (schema: Schema) => string[];\n canAddFields: (schema: Schema) => boolean;\n canEditField: (field: Field, schema: Schema) => boolean;\n canDeleteField: (field: Field, schema: Schema) => boolean;\n readonly fieldPermissions?: FieldPermissions;\n readonly supportsPii: boolean;\n}\n\ntype OffsetFind<T> = (\n query: OffsetQuery,\n options?: FindOptions,\n) => Promise<OffsetQueryResult<T>>;\n\n/** Fills source-neutral defaults over `input` and memoizes the load so the collection\n * query and the table columns share a single fetch. */\nexport function defineSchemaSource<T>(\n input: SchemaSourceInput<T>,\n): SchemaSource<T> {\n const {\n collectionId,\n paginationMode = 'offset',\n creatableFieldTypes = [],\n fieldPermissions,\n supportsPii = false,\n } = input;\n\n let loaded: Promise<LoadedSchema<T>> | undefined;\n let schema: Schema | undefined;\n\n const loadSchema = () =>\n (loaded ??= input\n .loadSchema()\n .then((result) => {\n schema = result.schema;\n return result;\n })\n .catch((error) => {\n loaded = undefined;\n throw error;\n }));\n\n const searchableFieldIds =\n input.searchableFieldIds ?? ((s) => [s.displayField]);\n\n const itemKey =\n input.itemKey ??\n ((item) =>\n String(\n (item as Record<string, unknown>)[schema?.idField ?? '_id'] ?? '',\n ));\n const itemName =\n input.itemName ??\n ((item) =>\n String(\n (item as Record<string, unknown>)[schema?.displayField ?? '_id'] ?? '',\n ));\n const canAddFields =\n input.canAddFields ?? ((s) => s.schemaPermissions?.createField ?? false);\n const canEditField =\n input.canEditField ??\n ((field, s) =>\n (s.schemaPermissions?.updateField ?? false) && !field.isSystem);\n const canDeleteField =\n input.canDeleteField ??\n ((field, s) =>\n (s.schemaPermissions?.deleteField ?? false) && !field.isSystem);\n\n const fetchData = async (\n query: OffsetQuery,\n ): Promise<OffsetQueryResult<T>> => {\n const { backend, schema: loadedSchema } = await loadSchema();\n return (backend.find as OffsetFind<T>)(query, {\n searchableFieldIds: searchableFieldIds(loadedSchema),\n });\n };\n\n return {\n collectionId,\n loadSchema,\n collectionConfig: {\n queryName: collectionId,\n paginationMode,\n fetchData,\n itemKey,\n itemName,\n },\n creatableFieldTypes,\n searchableFieldIds,\n canAddFields,\n canEditField,\n canDeleteField,\n fieldPermissions,\n supportsPii,\n };\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["sourceFetchData","source","query","backend","schema","loadSchema","visibleColumns","columns","find","searchableFieldIds","length","defineSchemaSource","input","collectionId","paginationMode","creatableFieldTypes","fieldTypes","fieldPermissions","supportsPii","fieldModalText","references","loaded","then","result","catch","error","undefined","s","displayField","itemKey","item","_schema","String","idField","itemName","_schema2","canAddFields","_s$schemaPermissions","schemaPermissions","createField","canEditField","field","_s$schemaPermissions2","updateField","isSystem","canDeleteField","_s$schemaPermissions3","deleteField","getFieldValue","id","setFieldValue","value"],"sources":["../../../src/types/SchemaSource.ts"],"sourcesContent":["import type { Field, PatternsFieldType } from './Field';\nimport type { FieldTypeDefinition } from './FieldTypeDefinition';\nimport type { Schema, LoadedSchema, FindOptions } from './Schema';\nimport type { FieldModalText, FieldPermissions } from './FieldsSource';\nimport type {\n OffsetQuery,\n OffsetQueryResult,\n} from '../hooks/paginationModeConfig';\n\n/** A field type a source allows creating. Declare one entry per\n * `patternsType` — the type is the entry's identity. */\nexport interface CreatableFieldType {\n patternsType: PatternsFieldType;\n /** Custom display name. Absent ⇒ the UI's standard name for this type. */\n label?: string;\n /** Custom name-input placeholder. Absent ⇒ the UI's standard placeholder. */\n namePlaceholder?: string;\n /** A one-line description shown under the type in the add-field menu. */\n subtitle?: string;\n /** The group heading this type is listed under in the add-field menu, in\n * first-seen order. Types sharing a heading form one group. Absent ⇒\n * ungrouped. */\n group?: string;\n}\n\n/** What a caller passes. Only `collectionId` and `loadSchema` are required. */\nexport interface SchemaSourceInput<T> {\n collectionId: string;\n loadSchema: () => Promise<LoadedSchema<T>>;\n /** Sources for collections this one references, keyed by the referenced\n * collection id. A renderer resolves a reference field through the matching\n * entry — its `loadSchema` gives the referenced schema and `sourceFetchData`\n * queries the referenced items. Default: none. */\n references?: Record<string, SchemaSource<any>>;\n paginationMode?: 'offset';\n /** Stable row identity. Default: `row[idField]`. */\n itemKey?: (item: T) => string;\n /** Row display label. Default: `row[displayField]`. */\n itemName?: (item: T) => string;\n /** Fields free-text search runs against. Default: `[displayField]`. */\n searchableFieldIds?: (schema: Schema) => string[];\n /** Field types the add-field modal offers. Default: none. */\n creatableFieldTypes?: CreatableFieldType[];\n /** Consumer-defined field types. A field with `type: 'CUSTOM'` resolves its\n * definition here by `customType`. Default: none. */\n fieldTypes?: FieldTypeDefinition[];\n /** Default: `schemaPermissions.createField`. */\n canAddFields?: (schema: Schema) => boolean;\n /** Default: `schemaPermissions.updateField && !field.isSystem`. */\n canEditField?: (field: Field, schema: Schema) => boolean;\n /** Default: `schemaPermissions.deleteField && !field.isSystem`. */\n canDeleteField?: (field: Field, schema: Schema) => boolean;\n /** Permission defaults shown in the modal. Absent ⇒ no permissions section. */\n fieldPermissions?: FieldPermissions;\n /** Default: `false`. */\n supportsPii?: boolean;\n /** Title and subtitle for the add/edit field modal. Absent ⇒ generic default. */\n fieldModalText?: FieldModalText;\n /** The value of a field on an item. Default: `item[field.id]`. */\n getFieldValue?: (item: T, field: Field) => unknown;\n /** Writes a field's value on an item, returning the updated item.\n * Default: `{ ...item, [field.id]: value }`. */\n setFieldValue?: (item: T, field: Field, value: unknown) => T;\n}\n\n/** The resolved source: defaults filled, `loadSchema` memoized. */\nexport interface SchemaSource<T> {\n readonly collectionId: string;\n loadSchema: () => Promise<LoadedSchema<T>>;\n readonly paginationMode: 'offset';\n /** Stable row identity. */\n itemKey: (item: T) => string;\n /** Row display label. */\n itemName: (item: T) => string;\n /** Sources for referenced collections, keyed by referenced collection id. */\n readonly references: Record<string, SchemaSource<any>>;\n readonly creatableFieldTypes: CreatableFieldType[];\n readonly fieldTypes: FieldTypeDefinition[];\n searchableFieldIds: (schema: Schema) => string[];\n canAddFields: (schema: Schema) => boolean;\n canEditField: (field: Field, schema: Schema) => boolean;\n canDeleteField: (field: Field, schema: Schema) => boolean;\n readonly fieldPermissions?: FieldPermissions;\n readonly supportsPii: boolean;\n readonly fieldModalText?: FieldModalText;\n /** The value of a field on an item. */\n getFieldValue: (item: T, field: Field) => unknown;\n /** Writes a field's value on an item, returning the updated item. */\n setFieldValue: (item: T, field: Field, value: unknown) => T;\n}\n\ntype OffsetFind<T> = (\n query: OffsetQuery,\n options?: FindOptions,\n) => Promise<OffsetQueryResult<T>>;\n\n/** The collection fetch derived from a source: loads once, then queries the\n * backend's `find`.\n *\n * Free-text search covers the columns the page is showing: the table keeps\n * `query.columns` in sync with them, so the scope comes off the query rather\n * than being threaded in. Falls back to the source's own `searchableFieldIds`\n * before any columns are known (or with no table attached). */\nexport function sourceFetchData<T>(\n source: SchemaSource<T>,\n): (query: OffsetQuery) => Promise<OffsetQueryResult<T>> {\n return async (query) => {\n const { backend, schema } = await source.loadSchema();\n // `columns` is the visible-column list; `fields` is the projection, which a\n // source-driven table doesn't set.\n const visibleColumns = query.columns;\n return (backend.find as OffsetFind<T>)(query, {\n searchableFieldIds: visibleColumns?.length\n ? visibleColumns\n : source.searchableFieldIds(schema),\n });\n };\n}\n\n/** Fills source-neutral defaults over `input` and memoizes the load so the collection\n * query and the table columns share a single fetch. */\nexport function defineSchemaSource<T>(\n input: SchemaSourceInput<T>,\n): SchemaSource<T> {\n const {\n collectionId,\n paginationMode = 'offset',\n creatableFieldTypes = [],\n fieldTypes = [],\n fieldPermissions,\n supportsPii = false,\n fieldModalText,\n references = {},\n } = input;\n\n let loaded: Promise<LoadedSchema<T>> | undefined;\n let schema: Schema | undefined;\n\n const loadSchema = () =>\n (loaded ??= input\n .loadSchema()\n .then((result) => {\n schema = result.schema;\n return result;\n })\n .catch((error) => {\n loaded = undefined;\n throw error;\n }));\n\n const searchableFieldIds =\n input.searchableFieldIds ?? ((s) => [s.displayField]);\n\n const itemKey =\n input.itemKey ??\n ((item) =>\n String(\n (item as Record<string, unknown>)[schema?.idField ?? '_id'] ?? '',\n ));\n const itemName =\n input.itemName ??\n ((item) =>\n String(\n (item as Record<string, unknown>)[schema?.displayField ?? '_id'] ?? '',\n ));\n const canAddFields =\n input.canAddFields ?? ((s) => s.schemaPermissions?.createField ?? false);\n const canEditField =\n input.canEditField ??\n ((field, s) =>\n (s.schemaPermissions?.updateField ?? false) && !field.isSystem);\n const canDeleteField =\n input.canDeleteField ??\n ((field, s) =>\n (s.schemaPermissions?.deleteField ?? false) && !field.isSystem);\n const getFieldValue =\n input.getFieldValue ??\n ((item, field) => (item as Record<string, unknown>)[field.id]);\n const setFieldValue =\n input.setFieldValue ??\n ((item, field, value) => ({ ...item, [field.id]: value } as T));\n\n return {\n collectionId,\n loadSchema,\n paginationMode,\n itemKey,\n itemName,\n references,\n creatableFieldTypes,\n fieldTypes,\n searchableFieldIds,\n canAddFields,\n canEditField,\n canDeleteField,\n fieldPermissions,\n supportsPii,\n fieldModalText,\n getFieldValue,\n setFieldValue,\n };\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _SchemaSource = require("../SchemaSource");
|
|
4
|
+
var _FieldTypeDefinition = require("../FieldTypeDefinition");
|
|
5
|
+
const loadSchema = () => Promise.reject(new Error('not loaded in this test'));
|
|
6
|
+
const Icon = () => null;
|
|
7
|
+
describe('defineSchemaSource — fieldTypes', () => {
|
|
8
|
+
it('defaults fieldTypes to an empty array', () => {
|
|
9
|
+
const source = (0, _SchemaSource.defineSchemaSource)({
|
|
10
|
+
collectionId: 'c1',
|
|
11
|
+
loadSchema
|
|
12
|
+
});
|
|
13
|
+
expect(source.fieldTypes).toEqual([]);
|
|
14
|
+
});
|
|
15
|
+
it('carries fieldTypes through to the resolved source untouched', () => {
|
|
16
|
+
const tags = (0, _FieldTypeDefinition.defineFieldType)({
|
|
17
|
+
type: 'test.tags',
|
|
18
|
+
display: {
|
|
19
|
+
label: 'Tags',
|
|
20
|
+
icons: {
|
|
21
|
+
Small: Icon,
|
|
22
|
+
Medium: Icon
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
filter: {
|
|
26
|
+
filterable: false
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
const source = (0, _SchemaSource.defineSchemaSource)({
|
|
30
|
+
collectionId: 'c1',
|
|
31
|
+
loadSchema,
|
|
32
|
+
fieldTypes: [tags]
|
|
33
|
+
});
|
|
34
|
+
expect(source.fieldTypes).toEqual([tags]);
|
|
35
|
+
expect(source.fieldTypes[0]).toBe(tags);
|
|
36
|
+
});
|
|
37
|
+
it('carries a full filter config through to the resolved source', () => {
|
|
38
|
+
const createFilter = () => ({});
|
|
39
|
+
const Component = () => null;
|
|
40
|
+
const tags = (0, _FieldTypeDefinition.defineFieldType)({
|
|
41
|
+
type: 'test.tags',
|
|
42
|
+
display: {
|
|
43
|
+
label: 'Tags',
|
|
44
|
+
icons: {
|
|
45
|
+
Small: Icon,
|
|
46
|
+
Medium: Icon
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
filter: {
|
|
50
|
+
createFilter,
|
|
51
|
+
Component
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
const source = (0, _SchemaSource.defineSchemaSource)({
|
|
55
|
+
collectionId: 'c1',
|
|
56
|
+
loadSchema,
|
|
57
|
+
fieldTypes: [tags]
|
|
58
|
+
});
|
|
59
|
+
expect(source.fieldTypes[0].filter).toEqual({
|
|
60
|
+
createFilter,
|
|
61
|
+
Component
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
describe('isFilterTypeConfig', () => {
|
|
65
|
+
it('narrows an active filter config', () => {
|
|
66
|
+
expect((0, _FieldTypeDefinition.isFilterTypeConfig)({
|
|
67
|
+
createFilter: () => ({}),
|
|
68
|
+
Component: () => null
|
|
69
|
+
})).toBe(true);
|
|
70
|
+
});
|
|
71
|
+
it('rejects the opt-out variant', () => {
|
|
72
|
+
expect((0, _FieldTypeDefinition.isFilterTypeConfig)({
|
|
73
|
+
filterable: false
|
|
74
|
+
})).toBe(false);
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
//# sourceMappingURL=defineSchemaSource.fieldTypes.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_SchemaSource","require","_FieldTypeDefinition","loadSchema","Promise","reject","Error","Icon","describe","it","source","defineSchemaSource","collectionId","expect","fieldTypes","toEqual","tags","defineFieldType","type","display","label","icons","Small","Medium","filter","filterable","toBe","createFilter","Component","isFilterTypeConfig"],"sources":["../../../../src/types/__tests__/defineSchemaSource.fieldTypes.spec.ts"],"sourcesContent":["import { defineSchemaSource } from '../SchemaSource';\nimport { defineFieldType, isFilterTypeConfig } from '../FieldTypeDefinition';\nimport type { Filter } from '../../model';\n\nconst loadSchema = () => Promise.reject(new Error('not loaded in this test'));\n\nconst Icon = () => null;\n\ndescribe('defineSchemaSource — fieldTypes', () => {\n it('defaults fieldTypes to an empty array', () => {\n const source = defineSchemaSource({ collectionId: 'c1', loadSchema });\n\n expect(source.fieldTypes).toEqual([]);\n });\n\n it('carries fieldTypes through to the resolved source untouched', () => {\n const tags = defineFieldType<string[]>({\n type: 'test.tags',\n display: { label: 'Tags', icons: { Small: Icon, Medium: Icon } },\n filter: { filterable: false },\n });\n const source = defineSchemaSource({\n collectionId: 'c1',\n loadSchema,\n fieldTypes: [tags],\n });\n\n expect(source.fieldTypes).toEqual([tags]);\n expect(source.fieldTypes[0]).toBe(tags);\n });\n\n it('carries a full filter config through to the resolved source', () => {\n const createFilter = () => ({} as Filter<string[]>);\n const Component = () => null;\n const tags = defineFieldType<string[]>({\n type: 'test.tags',\n display: { label: 'Tags', icons: { Small: Icon, Medium: Icon } },\n filter: { createFilter, Component },\n });\n const source = defineSchemaSource({\n collectionId: 'c1',\n loadSchema,\n fieldTypes: [tags],\n });\n\n expect(source.fieldTypes[0].filter).toEqual({ createFilter, Component });\n });\n\n describe('isFilterTypeConfig', () => {\n it('narrows an active filter config', () => {\n expect(\n isFilterTypeConfig({\n createFilter: () => ({} as Filter<string[]>),\n Component: () => null,\n }),\n ).toBe(true);\n });\n\n it('rejects the opt-out variant', () => {\n expect(isFilterTypeConfig({ filterable: false })).toBe(false);\n });\n });\n});\n"],"mappings":";;AAAA,IAAAA,aAAA,GAAAC,OAAA;AACA,IAAAC,oBAAA,GAAAD,OAAA;AAGA,MAAME,UAAU,GAAGA,CAAA,KAAMC,OAAO,CAACC,MAAM,CAAC,IAAIC,KAAK,CAAC,yBAAyB,CAAC,CAAC;AAE7E,MAAMC,IAAI,GAAGA,CAAA,KAAM,IAAI;AAEvBC,QAAQ,CAAC,iCAAiC,EAAE,MAAM;EAChDC,EAAE,CAAC,uCAAuC,EAAE,MAAM;IAChD,MAAMC,MAAM,GAAG,IAAAC,gCAAkB,EAAC;MAAEC,YAAY,EAAE,IAAI;MAAET;IAAW,CAAC,CAAC;IAErEU,MAAM,CAACH,MAAM,CAACI,UAAU,CAAC,CAACC,OAAO,CAAC,EAAE,CAAC;EACvC,CAAC,CAAC;EAEFN,EAAE,CAAC,6DAA6D,EAAE,MAAM;IACtE,MAAMO,IAAI,GAAG,IAAAC,oCAAe,EAAW;MACrCC,IAAI,EAAE,WAAW;MACjBC,OAAO,EAAE;QAAEC,KAAK,EAAE,MAAM;QAAEC,KAAK,EAAE;UAAEC,KAAK,EAAEf,IAAI;UAAEgB,MAAM,EAAEhB;QAAK;MAAE,CAAC;MAChEiB,MAAM,EAAE;QAAEC,UAAU,EAAE;MAAM;IAC9B,CAAC,CAAC;IACF,MAAMf,MAAM,GAAG,IAAAC,gCAAkB,EAAC;MAChCC,YAAY,EAAE,IAAI;MAClBT,UAAU;MACVW,UAAU,EAAE,CAACE,IAAI;IACnB,CAAC,CAAC;IAEFH,MAAM,CAACH,MAAM,CAACI,UAAU,CAAC,CAACC,OAAO,CAAC,CAACC,IAAI,CAAC,CAAC;IACzCH,MAAM,CAACH,MAAM,CAACI,UAAU,CAAC,CAAC,CAAC,CAAC,CAACY,IAAI,CAACV,IAAI,CAAC;EACzC,CAAC,CAAC;EAEFP,EAAE,CAAC,6DAA6D,EAAE,MAAM;IACtE,MAAMkB,YAAY,GAAGA,CAAA,MAAO,CAAC,CAAC,CAAqB;IACnD,MAAMC,SAAS,GAAGA,CAAA,KAAM,IAAI;IAC5B,MAAMZ,IAAI,GAAG,IAAAC,oCAAe,EAAW;MACrCC,IAAI,EAAE,WAAW;MACjBC,OAAO,EAAE;QAAEC,KAAK,EAAE,MAAM;QAAEC,KAAK,EAAE;UAAEC,KAAK,EAAEf,IAAI;UAAEgB,MAAM,EAAEhB;QAAK;MAAE,CAAC;MAChEiB,MAAM,EAAE;QAAEG,YAAY;QAAEC;MAAU;IACpC,CAAC,CAAC;IACF,MAAMlB,MAAM,GAAG,IAAAC,gCAAkB,EAAC;MAChCC,YAAY,EAAE,IAAI;MAClBT,UAAU;MACVW,UAAU,EAAE,CAACE,IAAI;IACnB,CAAC,CAAC;IAEFH,MAAM,CAACH,MAAM,CAACI,UAAU,CAAC,CAAC,CAAC,CAACU,MAAM,CAAC,CAACT,OAAO,CAAC;MAAEY,YAAY;MAAEC;IAAU,CAAC,CAAC;EAC1E,CAAC,CAAC;EAEFpB,QAAQ,CAAC,oBAAoB,EAAE,MAAM;IACnCC,EAAE,CAAC,iCAAiC,EAAE,MAAM;MAC1CI,MAAM,CACJ,IAAAgB,uCAAkB,EAAC;QACjBF,YAAY,EAAEA,CAAA,MAAO,CAAC,CAAC,CAAqB;QAC5CC,SAAS,EAAEA,CAAA,KAAM;MACnB,CAAC,CACH,CAAC,CAACF,IAAI,CAAC,IAAI,CAAC;IACd,CAAC,CAAC;IAEFjB,EAAE,CAAC,6BAA6B,EAAE,MAAM;MACtCI,MAAM,CAAC,IAAAgB,uCAAkB,EAAC;QAAEJ,UAAU,EAAE;MAAM,CAAC,CAAC,CAAC,CAACC,IAAI,CAAC,KAAK,CAAC;IAC/D,CAAC,CAAC;EACJ,CAAC,CAAC;AACJ,CAAC,CAAC","ignoreList":[]}
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"fields.audio.button.add": "Add Audio ",
|
|
18
18
|
"cairo.collectionPage.nested.expandAll.tooltip": "Expand all",
|
|
19
19
|
"cairo.customFields.addCustomField.modal.add.CTA": "Add Field",
|
|
20
|
-
"cairo.import.subtitle": "
|
|
20
|
+
"cairo.import.subtitle": "Add items in bulk by uploading a CSV file.",
|
|
21
21
|
"cairo.tags.manageTags.modal.deleteModal.body.asLabels": "<text>The label <name>\"{name}\"</name> might be in use. Deleting this label will also remove it from all of the items it's assigned to.</text>",
|
|
22
22
|
"cairo.import.progressLabel": "Imported {processed} of {total} rows",
|
|
23
23
|
"cairo.import.done": "Done",
|
|
@@ -88,11 +88,14 @@
|
|
|
88
88
|
"cairo.dragAndDrop.leaveSite.modal.cancel.CTA": "Cancel",
|
|
89
89
|
"cairo.tags.manageTags.modal.deleteModal.delete.CTA": "Delete",
|
|
90
90
|
"cairo.updatedView.collectionPage.toast.cta": "Refresh View",
|
|
91
|
+
"cairo.editableTable.dateTime.placeholder.hour": "HH",
|
|
91
92
|
"cairo.customFields.addCustomField.modal.PII-setting.toggle.createNote": "PII settings can’t be changed later.",
|
|
92
93
|
"cairo.tags.popover.assignFolder.tooltip": "Tags can't be assigned to folders.",
|
|
94
|
+
"cairo.editableTable.dateTime.placeholder.month": "MM",
|
|
93
95
|
"cairo.customFields.fieldType.date.invalid.value": "Enter a date that follows this format: {dateFormat}",
|
|
94
96
|
"cairo.archivedFields.more-actions.tooltip": "More actions",
|
|
95
97
|
"cairo.customFields.fieldType.dropdownList.placeholder": "e.g., Italy",
|
|
98
|
+
"cairo.editableTable.dateTime.placeholder": "Choose a date and time",
|
|
96
99
|
"cairo.filtersPanel.numRange.maxRange.error": "‘To’ value must be greater than the ‘From’ value.",
|
|
97
100
|
"cairo.import.fileReadFailed": "Couldn’t read this file. Check your internet connection and that the file hasn’t been moved or deleted.",
|
|
98
101
|
"cairo.setupWidget.step.inProgress": "In progress",
|
|
@@ -136,6 +139,7 @@
|
|
|
136
139
|
"cairo.tags.manageTags.modal.list.create.CTA": "Create <name>\"{tagName}\"</name>",
|
|
137
140
|
"cairo.export.GetExportAsyncJob.job-not-found.error": "Unable to export due to a technical issue on our end.",
|
|
138
141
|
"fields.audio.more_actions_tooltip": "More actions",
|
|
142
|
+
"cairo.editableTable.dateTime.placeholder.day": "DD",
|
|
139
143
|
"cairo.replace-image.tooltip": "Replace image",
|
|
140
144
|
"cairo.tags.filterPanel.dropdown.title.asLabels": "Labels",
|
|
141
145
|
"cairo.filtersPanel.search.clearButton": "Clear search",
|
|
@@ -158,6 +162,7 @@
|
|
|
158
162
|
"cairo.table.custom-columns.subtitle": "Choose which columns to show.",
|
|
159
163
|
"cairo.customFields.addCustomField.modal.advancedSettings.read": "Read",
|
|
160
164
|
"cairo.filterOperator.equals": "Equals",
|
|
165
|
+
"cairo.editableTable.dateTime.ariaLabel.time": "Time",
|
|
161
166
|
"cairo.customFields.fieldType.dateAndTime.Name.placeholder": "e.g., Timestamp",
|
|
162
167
|
"cairo.customFields.addCustomField.modal.PII": "This field can't be used to store personally identifiable information (PII).",
|
|
163
168
|
"cairo.dragAndDrop.reorderMode.toolbar.title.learnMore": "Learn more",
|
|
@@ -184,6 +189,7 @@
|
|
|
184
189
|
"cairo.filtersPanel.date.7days": "Last 7 days",
|
|
185
190
|
"cairo.customFields.fieldType.longText.placeholder": "Enter text here",
|
|
186
191
|
"cairo.customFields.addCustomField.modal.fieldName": "Name",
|
|
192
|
+
"cairo.editableTable.dateTime.placeholder.minute": "MM",
|
|
187
193
|
"cairo.filterOperator.startsWith.tag": "starts with",
|
|
188
194
|
"cairo.tags.tagsWidget.subtitle.asLabels": "Labels help you filter and stay organized.",
|
|
189
195
|
"cairo.tags.loadTags.error.title": "We couldn’t load your tags",
|
|
@@ -364,6 +370,7 @@
|
|
|
364
370
|
"airo.tags.collectionPage.popover.emptyState.body.asLabels": "Labels help you filter and organize your items.",
|
|
365
371
|
"cairo.folders.showAll.button": "Show All",
|
|
366
372
|
"cairo.dragAndDrop.reorderMode.discardChanges.description": "Are you sure you want to cancel changes? Your changes won’t be saved.",
|
|
373
|
+
"cairo.editableTable.dateTime.ariaLabel.date": "Date",
|
|
367
374
|
"cairo.filterOperator.lessThan.tag": "less than",
|
|
368
375
|
"cairo.tags.tagsWidget.emptyState.body": "Tags help you filter and organize your items.",
|
|
369
376
|
"cairo.customFields.fieldType.date.placeholder": "Select a date",
|
|
@@ -418,6 +425,7 @@
|
|
|
418
425
|
"cairo.table.custom-columns.button.cta": "Customize",
|
|
419
426
|
"cairo.customFields.addCustomField.modal.sameName.error": "A field with this name already exists. Try a different name.",
|
|
420
427
|
"cairo.deleteView.Success.toast": "\"{viewName}\" was deleted.",
|
|
428
|
+
"cairo.editableTable.dateTime.placeholder.year": "YYYY",
|
|
421
429
|
"cairo.filtersPanel.sections.default.title": "More filters",
|
|
422
430
|
"cairo.tags.tagsWidget.input.placeholder": "Enter new tag name",
|
|
423
431
|
"cairo.entity.item": "{num, plural, =0 {items} =1 {item} other {items}}",
|
|
@@ -736,7 +744,7 @@
|
|
|
736
744
|
"cairo.tags.fqdn-not-found.manageTagsModal.error": "Unable to complete this action.",
|
|
737
745
|
"cairo.tags.tagsWidget.options.add.CTA.asLabels": "Create \"{tagName}\"",
|
|
738
746
|
"cairo.setupWidget.step.lockedTooltip": "You don’t have access to this step. Ask the site owner for permission.",
|
|
739
|
-
"cairo.import.title": "Import
|
|
747
|
+
"cairo.import.title": "Import a CSV file",
|
|
740
748
|
"cairo.dragAndDrop.note": "Note: Any changes made to the order of your items will appear on your live site.",
|
|
741
749
|
"cairo.tags.tagsWidget.add.CTA.asLabels": "Assign Labels",
|
|
742
750
|
"cairo.filtersPanel.date.from.placeholder": "From"
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"fields.audio.button.add": "Add Audio ",
|
|
18
18
|
"cairo.collectionPage.nested.expandAll.tooltip": "Expand all",
|
|
19
19
|
"cairo.customFields.addCustomField.modal.add.CTA": "Add Field",
|
|
20
|
-
"cairo.import.subtitle": "
|
|
20
|
+
"cairo.import.subtitle": "Add items in bulk by uploading a CSV file.",
|
|
21
21
|
"cairo.tags.manageTags.modal.deleteModal.body.asLabels": "<text>The label <name>\"{name}\"</name> might be in use. Deleting this label will also remove it from all of the items it's assigned to.</text>",
|
|
22
22
|
"cairo.import.progressLabel": "Imported {processed} of {total} rows",
|
|
23
23
|
"cairo.import.done": "Done",
|
|
@@ -88,11 +88,14 @@
|
|
|
88
88
|
"cairo.dragAndDrop.leaveSite.modal.cancel.CTA": "Cancel",
|
|
89
89
|
"cairo.tags.manageTags.modal.deleteModal.delete.CTA": "Delete",
|
|
90
90
|
"cairo.updatedView.collectionPage.toast.cta": "Refresh View",
|
|
91
|
+
"cairo.editableTable.dateTime.placeholder.hour": "HH",
|
|
91
92
|
"cairo.customFields.addCustomField.modal.PII-setting.toggle.createNote": "PII settings can’t be changed later.",
|
|
92
93
|
"cairo.tags.popover.assignFolder.tooltip": "Tags can't be assigned to folders.",
|
|
94
|
+
"cairo.editableTable.dateTime.placeholder.month": "MM",
|
|
93
95
|
"cairo.customFields.fieldType.date.invalid.value": "Enter a date that follows this format: {dateFormat}",
|
|
94
96
|
"cairo.archivedFields.more-actions.tooltip": "More actions",
|
|
95
97
|
"cairo.customFields.fieldType.dropdownList.placeholder": "e.g., Italy",
|
|
98
|
+
"cairo.editableTable.dateTime.placeholder": "Choose a date and time",
|
|
96
99
|
"cairo.filtersPanel.numRange.maxRange.error": "‘To’ value must be greater than the ‘From’ value.",
|
|
97
100
|
"cairo.import.fileReadFailed": "Couldn’t read this file. Check your internet connection and that the file hasn’t been moved or deleted.",
|
|
98
101
|
"cairo.setupWidget.step.inProgress": "In progress",
|
|
@@ -136,6 +139,7 @@
|
|
|
136
139
|
"cairo.tags.manageTags.modal.list.create.CTA": "Create <name>\"{tagName}\"</name>",
|
|
137
140
|
"cairo.export.GetExportAsyncJob.job-not-found.error": "Unable to export due to a technical issue on our end.",
|
|
138
141
|
"fields.audio.more_actions_tooltip": "More actions",
|
|
142
|
+
"cairo.editableTable.dateTime.placeholder.day": "DD",
|
|
139
143
|
"cairo.replace-image.tooltip": "Replace image",
|
|
140
144
|
"cairo.tags.filterPanel.dropdown.title.asLabels": "Labels",
|
|
141
145
|
"cairo.filtersPanel.search.clearButton": "Clear search",
|
|
@@ -158,6 +162,7 @@
|
|
|
158
162
|
"cairo.table.custom-columns.subtitle": "Choose which columns to show.",
|
|
159
163
|
"cairo.customFields.addCustomField.modal.advancedSettings.read": "Read",
|
|
160
164
|
"cairo.filterOperator.equals": "Equals",
|
|
165
|
+
"cairo.editableTable.dateTime.ariaLabel.time": "Time",
|
|
161
166
|
"cairo.customFields.fieldType.dateAndTime.Name.placeholder": "e.g., Timestamp",
|
|
162
167
|
"cairo.customFields.addCustomField.modal.PII": "This field can't be used to store personally identifiable information (PII).",
|
|
163
168
|
"cairo.dragAndDrop.reorderMode.toolbar.title.learnMore": "Learn more",
|
|
@@ -184,6 +189,7 @@
|
|
|
184
189
|
"cairo.filtersPanel.date.7days": "Last 7 days",
|
|
185
190
|
"cairo.customFields.fieldType.longText.placeholder": "Enter text here",
|
|
186
191
|
"cairo.customFields.addCustomField.modal.fieldName": "Name",
|
|
192
|
+
"cairo.editableTable.dateTime.placeholder.minute": "MM",
|
|
187
193
|
"cairo.filterOperator.startsWith.tag": "starts with",
|
|
188
194
|
"cairo.tags.tagsWidget.subtitle.asLabels": "Labels help you filter and stay organized.",
|
|
189
195
|
"cairo.tags.loadTags.error.title": "We couldn’t load your tags",
|
|
@@ -364,6 +370,7 @@
|
|
|
364
370
|
"airo.tags.collectionPage.popover.emptyState.body.asLabels": "Labels help you filter and organize your items.",
|
|
365
371
|
"cairo.folders.showAll.button": "Show All",
|
|
366
372
|
"cairo.dragAndDrop.reorderMode.discardChanges.description": "Are you sure you want to cancel changes? Your changes won’t be saved.",
|
|
373
|
+
"cairo.editableTable.dateTime.ariaLabel.date": "Date",
|
|
367
374
|
"cairo.filterOperator.lessThan.tag": "less than",
|
|
368
375
|
"cairo.tags.tagsWidget.emptyState.body": "Tags help you filter and organize your items.",
|
|
369
376
|
"cairo.customFields.fieldType.date.placeholder": "Select a date",
|
|
@@ -418,6 +425,7 @@
|
|
|
418
425
|
"cairo.table.custom-columns.button.cta": "Customize",
|
|
419
426
|
"cairo.customFields.addCustomField.modal.sameName.error": "A field with this name already exists. Try a different name.",
|
|
420
427
|
"cairo.deleteView.Success.toast": "\"{viewName}\" was deleted.",
|
|
428
|
+
"cairo.editableTable.dateTime.placeholder.year": "YYYY",
|
|
421
429
|
"cairo.filtersPanel.sections.default.title": "More filters",
|
|
422
430
|
"cairo.tags.tagsWidget.input.placeholder": "Enter new tag name",
|
|
423
431
|
"cairo.entity.item": "{num, plural, =0 {items} =1 {item} other {items}}",
|
|
@@ -736,7 +744,7 @@
|
|
|
736
744
|
"cairo.tags.fqdn-not-found.manageTagsModal.error": "Unable to complete this action.",
|
|
737
745
|
"cairo.tags.tagsWidget.options.add.CTA.asLabels": "Create \"{tagName}\"",
|
|
738
746
|
"cairo.setupWidget.step.lockedTooltip": "You don’t have access to this step. Ask the site owner for permission.",
|
|
739
|
-
"cairo.import.title": "Import
|
|
747
|
+
"cairo.import.title": "Import a CSV file",
|
|
740
748
|
"cairo.dragAndDrop.note": "Note: Any changes made to the order of your items will appear on your live site.",
|
|
741
749
|
"cairo.tags.tagsWidget.add.CTA.asLabels": "Assign Labels",
|
|
742
750
|
"cairo.filtersPanel.date.from.placeholder": "From"
|