@panneau/fields 4.1.1 → 5.0.0-alpha.1
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/README.md +74 -0
- package/dist/boolean/BooleanField.d.ts +11 -0
- package/dist/boolean/BooleanField.d.ts.map +1 -0
- package/dist/boolean/BooleanField.js +67 -0
- package/dist/boolean/BooleanField.js.map +1 -0
- package/dist/boolean/index.d.ts +2 -0
- package/dist/boolean/index.d.ts.map +1 -0
- package/dist/boolean/index.js +1 -0
- package/dist/color/ColorField.css +33 -0
- package/dist/color/ColorField.d.ts +16 -0
- package/dist/color/ColorField.d.ts.map +1 -0
- package/dist/color/ColorField.js +187 -0
- package/dist/color/ColorField.js.map +1 -0
- package/dist/color/ColorField.module.js +14 -0
- package/dist/color/ColorField.module.js.map +1 -0
- package/dist/color/index.d.ts +2 -0
- package/dist/color/index.d.ts.map +1 -0
- package/dist/color/index.js +1 -0
- package/dist/date/DateField.d.ts +16 -0
- package/dist/date/DateField.d.ts.map +1 -0
- package/dist/date/DateField.js +132 -0
- package/dist/date/DateField.js.map +1 -0
- package/dist/date/index.d.ts +2 -0
- package/dist/date/index.d.ts.map +1 -0
- package/dist/date/index.js +1 -0
- package/dist/datetime/DateTimeField.d.ts +22 -0
- package/dist/datetime/DateTimeField.d.ts.map +1 -0
- package/dist/datetime/DateTimeField.js +78 -0
- package/dist/datetime/DateTimeField.js.map +1 -0
- package/dist/datetime/index.d.ts +2 -0
- package/dist/datetime/index.d.ts.map +1 -0
- package/dist/datetime/index.js +1 -0
- package/dist/email/EmailField.d.ts +8 -0
- package/dist/email/EmailField.d.ts.map +1 -0
- package/dist/email/EmailField.js +84 -0
- package/dist/email/EmailField.js.map +1 -0
- package/dist/email/index.d.ts +2 -0
- package/dist/email/index.d.ts.map +1 -0
- package/dist/email/index.js +1 -0
- package/dist/group/GroupField.css +14 -0
- package/dist/group/GroupField.d.ts +19 -0
- package/dist/group/GroupField.d.ts.map +1 -0
- package/dist/group/GroupField.js +140 -0
- package/dist/group/GroupField.js.map +1 -0
- package/dist/group/GroupField.module.js +8 -0
- package/dist/group/GroupField.module.js.map +1 -0
- package/dist/group/index.d.ts +2 -0
- package/dist/group/index.d.ts.map +1 -0
- package/dist/group/index.js +1 -0
- package/dist/index.d.ts +8 -12
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -134
- package/dist/locales/index.d.ts +15 -0
- package/dist/locales/index.d.ts.map +1 -0
- package/dist/locales/index.js +21 -0
- package/dist/locales/index.js.map +1 -0
- package/dist/localized/LocalizedField.css +9 -0
- package/dist/localized/LocalizedField.d.ts +36 -0
- package/dist/localized/LocalizedField.d.ts.map +1 -0
- package/dist/localized/LocalizedField.js +207 -0
- package/dist/localized/LocalizedField.js.map +1 -0
- package/dist/localized/LocalizedField.module.js +12 -0
- package/dist/localized/LocalizedField.module.js.map +1 -0
- package/dist/localized/index.d.ts +2 -0
- package/dist/localized/index.d.ts.map +1 -0
- package/dist/localized/index.js +1 -0
- package/dist/missing/MissingField.css +18 -0
- package/dist/missing/MissingField.d.ts +7 -0
- package/dist/missing/MissingField.d.ts.map +1 -0
- package/dist/missing/MissingField.js +68 -0
- package/dist/missing/MissingField.js.map +1 -0
- package/dist/missing/MissingField.module.js +14 -0
- package/dist/missing/MissingField.module.js.map +1 -0
- package/dist/number/NumberField.d.ts +23 -0
- package/dist/number/NumberField.d.ts.map +1 -0
- package/dist/number/NumberField.js +175 -0
- package/dist/number/NumberField.js.map +1 -0
- package/dist/number/index.d.ts +2 -0
- package/dist/number/index.d.ts.map +1 -0
- package/dist/number/index.js +1 -0
- package/dist/relation/RelationField.css +43 -0
- package/dist/relation/RelationField.d.ts +48 -0
- package/dist/relation/RelationField.d.ts.map +1 -0
- package/dist/relation/RelationField.js +328 -0
- package/dist/relation/RelationField.js.map +1 -0
- package/dist/relation/RelationField.module.js +20 -0
- package/dist/relation/RelationField.module.js.map +1 -0
- package/dist/relation/index.d.ts +3 -0
- package/dist/relation/index.d.ts.map +1 -0
- package/dist/relation/index.js +3 -0
- package/dist/repeater/RepeaterField.css +80 -0
- package/dist/repeater/RepeaterField.d.ts +29 -0
- package/dist/repeater/RepeaterField.d.ts.map +1 -0
- package/dist/repeater/RepeaterField.js +220 -0
- package/dist/repeater/RepeaterField.js.map +1 -0
- package/dist/repeater/RepeaterField.module.js +26 -0
- package/dist/repeater/RepeaterField.module.js.map +1 -0
- package/dist/repeater/index.d.ts +2 -0
- package/dist/repeater/index.d.ts.map +1 -0
- package/dist/repeater/index.js +1 -0
- package/dist/select/SelectField.css +5 -0
- package/dist/select/SelectField.d.ts +38 -0
- package/dist/select/SelectField.d.ts.map +1 -0
- package/dist/select/SelectField.js +434 -0
- package/dist/select/SelectField.js.map +1 -0
- package/dist/select/SelectField.module.js +8 -0
- package/dist/select/SelectField.module.js.map +1 -0
- package/dist/select/index.d.ts +2 -0
- package/dist/select/index.d.ts.map +1 -0
- package/dist/select/index.js +1 -0
- package/dist/shared/DefinitionField.d.ts +32 -0
- package/dist/shared/DefinitionField.d.ts.map +1 -0
- package/dist/shared/DefinitionField.js +153 -0
- package/dist/shared/DefinitionField.js.map +1 -0
- package/dist/shared/builtIn.d.ts +17 -0
- package/dist/shared/builtIn.d.ts.map +1 -0
- package/dist/shared/builtIn.js +52 -0
- package/dist/shared/builtIn.js.map +1 -0
- package/dist/shared/context.d.ts +55 -0
- package/dist/shared/context.d.ts.map +1 -0
- package/dist/shared/context.js +72 -0
- package/dist/shared/context.js.map +1 -0
- package/dist/shared/cx.d.ts +3 -0
- package/dist/shared/cx.d.ts.map +1 -0
- package/dist/shared/cx.js +9 -0
- package/dist/shared/cx.js.map +1 -0
- package/dist/shared/dates.d.ts +15 -0
- package/dist/shared/dates.d.ts.map +1 -0
- package/dist/shared/dates.js +49 -0
- package/dist/shared/dates.js.map +1 -0
- package/dist/shared/entry.d.ts +23 -0
- package/dist/shared/entry.d.ts.map +1 -0
- package/dist/shared/entry.js +45 -0
- package/dist/shared/entry.js.map +1 -0
- package/dist/shared/messages.d.ts +2 -0
- package/dist/shared/messages.d.ts.map +1 -0
- package/dist/shared/messages.js +1 -0
- package/dist/shared/relation.d.ts +73 -0
- package/dist/shared/relation.d.ts.map +1 -0
- package/dist/shared/relation.js +156 -0
- package/dist/shared/relation.js.map +1 -0
- package/dist/shared/types.d.ts +50 -0
- package/dist/shared/types.d.ts.map +1 -0
- package/dist/slug/SlugField.d.ts +24 -0
- package/dist/slug/SlugField.d.ts.map +1 -0
- package/dist/slug/SlugField.js +216 -0
- package/dist/slug/SlugField.js.map +1 -0
- package/dist/slug/index.d.ts +2 -0
- package/dist/slug/index.d.ts.map +1 -0
- package/dist/slug/index.js +1 -0
- package/dist/text/TextField.d.ts +24 -0
- package/dist/text/TextField.d.ts.map +1 -0
- package/dist/text/TextField.js +179 -0
- package/dist/text/TextField.js.map +1 -0
- package/dist/text/index.d.ts +2 -0
- package/dist/text/index.d.ts.map +1 -0
- package/dist/text/index.js +1 -0
- package/dist/textarea/TextAreaField.d.ts +14 -0
- package/dist/textarea/TextAreaField.d.ts.map +1 -0
- package/dist/textarea/TextAreaField.js +126 -0
- package/dist/textarea/TextAreaField.js.map +1 -0
- package/dist/textarea/index.d.ts +2 -0
- package/dist/textarea/index.d.ts.map +1 -0
- package/dist/textarea/index.js +1 -0
- package/dist/time/TimeField.d.ts +13 -0
- package/dist/time/TimeField.d.ts.map +1 -0
- package/dist/time/TimeField.js +49 -0
- package/dist/time/TimeField.js.map +1 -0
- package/dist/time/index.d.ts +2 -0
- package/dist/time/index.d.ts.map +1 -0
- package/dist/time/index.js +1 -0
- package/dist/url/UrlField.css +11 -0
- package/dist/url/UrlField.d.ts +16 -0
- package/dist/url/UrlField.d.ts.map +1 -0
- package/dist/url/UrlField.js +94 -0
- package/dist/url/UrlField.js.map +1 -0
- package/dist/url/UrlField.module.js +8 -0
- package/dist/url/UrlField.module.js.map +1 -0
- package/dist/url/index.d.ts +2 -0
- package/dist/url/index.d.ts.map +1 -0
- package/dist/url/index.js +1 -0
- package/package.json +108 -79
- package/assets/css/styles.css +0 -14
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NumberField.js","names":["min","max","disabled","readOnly","required","_c"],"sources":["../../src/number/NumberField.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\n\nimport { NumberInput } from '@panneau/ui';\n\nimport { getFieldProps, getRuleNumber, getSetting, isNumber, isString } from '../shared/entry';\nimport type { FieldEntryProps, FieldProps } from '../shared/types';\n\nexport interface NumberFieldProps extends FieldProps<number> {\n placeholder?: string;\n min?: number;\n max?: number;\n /** Step of the steppers and arrow keys. Defaults to 1. */\n step?: number;\n /** Format of the number, for the locale: decimals, percent, currency. */\n formatOptions?: Intl.NumberFormatOptions;\n /** Content after the number: a unit. */\n suffix?: ReactNode;\n controlClassName?: string;\n inputClassName?: string;\n}\n\n/** A number, formatted for the locale. An empty field is `null`. */\nexport function NumberField({\n value,\n onChange,\n min,\n max,\n disabled,\n readOnly,\n required,\n ...props\n}: NumberFieldProps) {\n return (\n <NumberInput\n {...props}\n value={value ?? null}\n onChange={(next) => onChange?.(next)}\n minValue={min}\n maxValue={max}\n isDisabled={disabled}\n isReadOnly={readOnly}\n isRequired={required}\n />\n );\n}\n\n/**\n * The `number` type: `min` and `max` from its rules, and settings `step`, `decimals` (the most\n * digits after the decimal point) and `suffix`.\n */\nexport function NumberFieldEntry(props: FieldEntryProps) {\n const { field } = props;\n const min = getRuleNumber(field, 'min');\n const max = getRuleNumber(field, 'max');\n const step = getSetting(field, 'step', isNumber);\n const decimals = getSetting(field, 'decimals', isNumber);\n const suffix = getSetting(field, 'suffix', isString);\n return (\n <NumberField\n {...getFieldProps(props)}\n value={isNumber(props.value) ? props.value : null}\n onChange={props.onChange}\n {...(min !== undefined ? { min } : {})}\n {...(max !== undefined ? { max } : {})}\n {...(step !== undefined ? { step } : {})}\n {...(decimals !== undefined\n ? { formatOptions: { maximumFractionDigits: decimals } }\n : {})}\n {...(suffix !== undefined ? { suffix } : {})}\n />\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/number/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { NumberField, NumberFieldEntry } from "./NumberField.js";
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
.panneau-multiple-u9IXr- {
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-direction: column;
|
|
4
|
+
gap: var(--panneau-space-2);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.panneau-selected-PL7VcQ {
|
|
8
|
+
display: flex;
|
|
9
|
+
flex-wrap: wrap;
|
|
10
|
+
gap: var(--panneau-space-1) var(--panneau-space-2);
|
|
11
|
+
margin: 0;
|
|
12
|
+
padding: 0;
|
|
13
|
+
list-style: none;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.panneau-reference-J8YpaW {
|
|
17
|
+
display: inline-flex;
|
|
18
|
+
align-items: center;
|
|
19
|
+
gap: var(--panneau-space-1);
|
|
20
|
+
min-height: var(--panneau-control-height-sm);
|
|
21
|
+
max-width: 100%;
|
|
22
|
+
padding-inline: var(--panneau-space-3) var(--panneau-space-1);
|
|
23
|
+
font-size: var(--panneau-font-size-sm);
|
|
24
|
+
background-color: var(--panneau-color-surface-sunken);
|
|
25
|
+
border: var(--panneau-border-width) solid var(--panneau-color-border);
|
|
26
|
+
border-radius: var(--panneau-radius-full);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.panneau-reference-J8YpaW:only-child,
|
|
30
|
+
.panneau-readOnly-UunIK0 .panneau-reference-J8YpaW {
|
|
31
|
+
padding-inline-end: var(--panneau-space-3);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.panneau-referenceLabel-ydQ0bU {
|
|
35
|
+
overflow: hidden;
|
|
36
|
+
text-overflow: ellipsis;
|
|
37
|
+
white-space: nowrap;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.panneau-none-niMk7v {
|
|
41
|
+
font-size: var(--panneau-font-size-md);
|
|
42
|
+
color: var(--panneau-color-text-muted);
|
|
43
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { type RelationReference, type RelationSource } from '../shared/relation';
|
|
2
|
+
import type { FieldEntryProps, FieldProps } from '../shared/types';
|
|
3
|
+
/** Results of a search in a relation source, as it types. */
|
|
4
|
+
export declare function useRelationSearch(source: RelationSource | null, resource: string, query: string, { enabled, delay }?: {
|
|
5
|
+
enabled?: boolean;
|
|
6
|
+
delay?: number;
|
|
7
|
+
}): {
|
|
8
|
+
items: RelationReference[];
|
|
9
|
+
isLoading: boolean;
|
|
10
|
+
};
|
|
11
|
+
/** Props of both single and multiple relation fields. */
|
|
12
|
+
export interface RelationFieldBaseProps extends Omit<FieldProps<never>, 'value' | 'onChange'> {
|
|
13
|
+
/** Id of the related resource, passed to the source. */
|
|
14
|
+
resource: string;
|
|
15
|
+
/** Where to search. Defaults to the fields context's. Without one, the field is read-only. */
|
|
16
|
+
source?: RelationSource | null;
|
|
17
|
+
/**
|
|
18
|
+
* Creates an item from the typed text, offered as "Create “…”" in the picker: it can open a
|
|
19
|
+
* dialog, and resolves with the new reference, or `null` when nothing was created. Defaults to
|
|
20
|
+
* the source's `create()`. `null` turns creating off.
|
|
21
|
+
*/
|
|
22
|
+
onCreate?: ((text: string) => Promise<RelationReference | null>) | null;
|
|
23
|
+
placeholder?: string;
|
|
24
|
+
controlClassName?: string;
|
|
25
|
+
}
|
|
26
|
+
export interface SingleRelationFieldProps extends RelationFieldBaseProps {
|
|
27
|
+
multiple?: false;
|
|
28
|
+
value?: RelationReference | null;
|
|
29
|
+
onChange?: (value: RelationReference | null) => void;
|
|
30
|
+
}
|
|
31
|
+
export interface MultipleRelationFieldProps extends RelationFieldBaseProps {
|
|
32
|
+
multiple: true;
|
|
33
|
+
value?: readonly RelationReference[] | null;
|
|
34
|
+
/** Called with the references. An empty list is `null`. */
|
|
35
|
+
onChange?: (value: RelationReference[] | null) => void;
|
|
36
|
+
}
|
|
37
|
+
export type RelationFieldProps = SingleRelationFieldProps | MultipleRelationFieldProps;
|
|
38
|
+
/**
|
|
39
|
+
* A reference to an item of another resource, or several with `multiple`, picked by searching a
|
|
40
|
+
* `RelationSource`. Values are references (`{ id, label }`), as items carry them; plain ids get
|
|
41
|
+
* their labels from the source's `resolve()`. When the source can `create()` (or with `onCreate`),
|
|
42
|
+
* the picker offers to create an item from the typed text. Without a source, the field shows its
|
|
43
|
+
* references and can't change them.
|
|
44
|
+
*/
|
|
45
|
+
export declare function RelationField(props: RelationFieldProps): import("react").JSX.Element;
|
|
46
|
+
/** The `relation` type: `resource` and `multiple`. Items search the fields context's source. */
|
|
47
|
+
export declare function RelationFieldEntry(props: FieldEntryProps): import("react").JSX.Element;
|
|
48
|
+
//# sourceMappingURL=RelationField.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RelationField.d.ts","sourceRoot":"","sources":["../../src/relation/RelationField.tsx"],"names":[],"mappings":"AASA,OAAO,EACH,KAAK,iBAAiB,EACtB,KAAK,cAAc,EAGtB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAMnE,6DAA6D;AAC7D,wBAAgB,iBAAiB,CAC7B,MAAM,EAAE,cAAc,GAAG,IAAI,EAC7B,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,EAAE,OAAc,EAAE,KAAW,EAAE,GAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAC5E;IAAE,KAAK,EAAE,iBAAiB,EAAE,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAmCpD;AAED,yDAAyD;AACzD,MAAM,WAAW,sBAAuB,SAAQ,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC;IACzF,wDAAwD;IACxD,QAAQ,EAAE,MAAM,CAAC;IACjB,8FAA8F;IAC9F,MAAM,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;IAC/B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC;IACxE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,wBAAyB,SAAQ,sBAAsB;IACpE,QAAQ,CAAC,EAAE,KAAK,CAAC;IACjB,KAAK,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI,KAAK,IAAI,CAAC;CACxD;AAED,MAAM,WAAW,0BAA2B,SAAQ,sBAAsB;IACtE,QAAQ,EAAE,IAAI,CAAC;IACf,KAAK,CAAC,EAAE,SAAS,iBAAiB,EAAE,GAAG,IAAI,CAAC;IAC5C,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,iBAAiB,EAAE,GAAG,IAAI,KAAK,IAAI,CAAC;CAC1D;AAED,MAAM,MAAM,kBAAkB,GAAG,wBAAwB,GAAG,0BAA0B,CAAC;AA+BvF;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,+BAyNtD;AAED,gGAAgG;AAChG,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,eAAe,+BAQxD"}
|
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
import { useFieldsContext } from "../shared/context.js";
|
|
2
|
+
import { cx } from "../shared/cx.js";
|
|
3
|
+
import { getFieldProps } from "../shared/entry.js";
|
|
4
|
+
import { messages } from "../shared/messages.js";
|
|
5
|
+
import { toReferences, useRelationReferences } from "../shared/relation.js";
|
|
6
|
+
import RelationField_module_default from "./RelationField.module.js";
|
|
7
|
+
import { c } from "react/compiler-runtime";
|
|
8
|
+
import { ComboBox, Fieldset, IconButton, usePanneauIntl } from "@panneau/ui";
|
|
9
|
+
import { useEffect, useState } from "react";
|
|
10
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
11
|
+
import { X } from "lucide-react";
|
|
12
|
+
//#region src/relation/RelationField.tsx
|
|
13
|
+
/** The id of the "Create “…”" option of the picker. */
|
|
14
|
+
var CREATE_ID = "\0create";
|
|
15
|
+
/** Results of a search in a relation source, as it types. */
|
|
16
|
+
function useRelationSearch(source, resource, query, { enabled = true, delay = 250 } = {}) {
|
|
17
|
+
const [state, setState] = useState({
|
|
18
|
+
key: "",
|
|
19
|
+
items: [],
|
|
20
|
+
isLoading: false
|
|
21
|
+
});
|
|
22
|
+
const key = `${resource}\u0000${query}`;
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
if (source === null || !enabled) return;
|
|
25
|
+
const controller = new AbortController();
|
|
26
|
+
const timer = setTimeout(() => {
|
|
27
|
+
setState((current) => ({
|
|
28
|
+
...current,
|
|
29
|
+
key,
|
|
30
|
+
isLoading: true
|
|
31
|
+
}));
|
|
32
|
+
source.search(resource, query, { signal: controller.signal }).then((items) => {
|
|
33
|
+
if (!controller.signal.aborted) setState({
|
|
34
|
+
key,
|
|
35
|
+
items,
|
|
36
|
+
isLoading: false
|
|
37
|
+
});
|
|
38
|
+
}).catch(() => {
|
|
39
|
+
if (!controller.signal.aborted) setState({
|
|
40
|
+
key,
|
|
41
|
+
items: [],
|
|
42
|
+
isLoading: false
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
}, delay);
|
|
46
|
+
return () => {
|
|
47
|
+
clearTimeout(timer);
|
|
48
|
+
controller.abort();
|
|
49
|
+
};
|
|
50
|
+
}, [
|
|
51
|
+
source,
|
|
52
|
+
resource,
|
|
53
|
+
query,
|
|
54
|
+
key,
|
|
55
|
+
enabled,
|
|
56
|
+
delay
|
|
57
|
+
]);
|
|
58
|
+
return {
|
|
59
|
+
items: state.items,
|
|
60
|
+
isLoading: state.isLoading || state.key !== key
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function References(t0) {
|
|
64
|
+
const $ = c(12);
|
|
65
|
+
const { references, onRemove, removeLabel } = t0;
|
|
66
|
+
const t1 = onRemove === void 0 && RelationField_module_default.readOnly;
|
|
67
|
+
let t2;
|
|
68
|
+
if ($[0] !== t1) {
|
|
69
|
+
t2 = cx(RelationField_module_default.selected, t1);
|
|
70
|
+
$[0] = t1;
|
|
71
|
+
$[1] = t2;
|
|
72
|
+
} else t2 = $[1];
|
|
73
|
+
let t3;
|
|
74
|
+
if ($[2] !== onRemove || $[3] !== references || $[4] !== removeLabel) {
|
|
75
|
+
let t4;
|
|
76
|
+
if ($[6] !== onRemove || $[7] !== removeLabel) {
|
|
77
|
+
t4 = (reference) => /* @__PURE__ */ jsxs("li", {
|
|
78
|
+
className: RelationField_module_default.reference,
|
|
79
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
80
|
+
className: RelationField_module_default.referenceLabel,
|
|
81
|
+
children: reference.label
|
|
82
|
+
}), onRemove !== void 0 ? /* @__PURE__ */ jsx(IconButton, {
|
|
83
|
+
icon: X,
|
|
84
|
+
size: "sm",
|
|
85
|
+
label: removeLabel(reference),
|
|
86
|
+
showTooltip: false,
|
|
87
|
+
onPress: () => onRemove(reference)
|
|
88
|
+
}) : null]
|
|
89
|
+
}, reference.id);
|
|
90
|
+
$[6] = onRemove;
|
|
91
|
+
$[7] = removeLabel;
|
|
92
|
+
$[8] = t4;
|
|
93
|
+
} else t4 = $[8];
|
|
94
|
+
t3 = references.map(t4);
|
|
95
|
+
$[2] = onRemove;
|
|
96
|
+
$[3] = references;
|
|
97
|
+
$[4] = removeLabel;
|
|
98
|
+
$[5] = t3;
|
|
99
|
+
} else t3 = $[5];
|
|
100
|
+
let t4;
|
|
101
|
+
if ($[9] !== t2 || $[10] !== t3) {
|
|
102
|
+
t4 = /* @__PURE__ */ jsx("ul", {
|
|
103
|
+
className: t2,
|
|
104
|
+
children: t3
|
|
105
|
+
});
|
|
106
|
+
$[9] = t2;
|
|
107
|
+
$[10] = t3;
|
|
108
|
+
$[11] = t4;
|
|
109
|
+
} else t4 = $[11];
|
|
110
|
+
return t4;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* A reference to an item of another resource, or several with `multiple`, picked by searching a
|
|
114
|
+
* `RelationSource`. Values are references (`{ id, label }`), as items carry them; plain ids get
|
|
115
|
+
* their labels from the source's `resolve()`. When the source can `create()` (or with `onCreate`),
|
|
116
|
+
* the picker offers to create an item from the typed text. Without a source, the field shows its
|
|
117
|
+
* references and can't change them.
|
|
118
|
+
*/
|
|
119
|
+
function RelationField(props) {
|
|
120
|
+
const intl = usePanneauIntl();
|
|
121
|
+
const context = useFieldsContext();
|
|
122
|
+
const source = props.source === void 0 ? context.relationSource : props.source;
|
|
123
|
+
const { resource, label, description, errors, disabled, readOnly, required, placeholder = intl.formatMessage(messages.search), onBlur, name, id, className, labelClassName, descriptionClassName, errorsClassName, controlClassName } = props;
|
|
124
|
+
const selected = useRelationReferences(source, resource, toReferences(props.value));
|
|
125
|
+
const [query, setQuery] = useState(null);
|
|
126
|
+
const [creating, setCreating] = useState(false);
|
|
127
|
+
const [createError, setCreateError] = useState(null);
|
|
128
|
+
const editable = source !== null && disabled !== true && readOnly !== true;
|
|
129
|
+
const { items: found, isLoading: searching } = useRelationSearch(source, resource, query ?? "", { enabled: editable });
|
|
130
|
+
const sourceCreate = source?.create;
|
|
131
|
+
const create = props.onCreate !== void 0 ? props.onCreate : sourceCreate !== void 0 && source?.canCreate?.(resource) !== false ? (text) => sourceCreate.call(source, resource, text) : null;
|
|
132
|
+
const text_0 = (query ?? "").trim();
|
|
133
|
+
const items = create !== null && text_0 !== "" && !searching && ![...found, ...selected].some((item) => item.label.toLocaleLowerCase(intl.locale) === text_0.toLocaleLowerCase(intl.locale)) ? [...found, {
|
|
134
|
+
id: CREATE_ID,
|
|
135
|
+
label: intl.formatMessage(messages.createRelation, { text: text_0 })
|
|
136
|
+
}] : found;
|
|
137
|
+
const isLoading = searching || creating;
|
|
138
|
+
const allErrors = createError !== null ? [...errors ?? [], createError] : errors;
|
|
139
|
+
/** Creates an item from the text, then adds its reference with `add`. */
|
|
140
|
+
const createFrom = (add) => {
|
|
141
|
+
if (create === null) return;
|
|
142
|
+
setCreating(true);
|
|
143
|
+
setCreateError(null);
|
|
144
|
+
create(text_0).then((reference) => {
|
|
145
|
+
if (reference !== null) {
|
|
146
|
+
add(reference);
|
|
147
|
+
setQuery(null);
|
|
148
|
+
}
|
|
149
|
+
}).catch(() => setCreateError(intl.formatMessage(messages.createRelationFailed, { text: text_0 }))).finally(() => setCreating(false));
|
|
150
|
+
};
|
|
151
|
+
const removeLabel = (reference_0) => `${intl.formatMessage(messages.remove)} ${reference_0.label}`;
|
|
152
|
+
const chrome = {
|
|
153
|
+
legend: label,
|
|
154
|
+
errors: allErrors,
|
|
155
|
+
isRequired: required,
|
|
156
|
+
className,
|
|
157
|
+
legendClassName: labelClassName,
|
|
158
|
+
descriptionClassName,
|
|
159
|
+
errorsClassName
|
|
160
|
+
};
|
|
161
|
+
if (!editable) return /* @__PURE__ */ jsx(Fieldset, {
|
|
162
|
+
...chrome,
|
|
163
|
+
description: source === null && disabled !== true && readOnly !== true ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
164
|
+
description,
|
|
165
|
+
" ",
|
|
166
|
+
intl.formatMessage(messages.relationUnavailable)
|
|
167
|
+
] }) : description,
|
|
168
|
+
children: selected.length > 0 ? /* @__PURE__ */ jsx(References, {
|
|
169
|
+
references: selected,
|
|
170
|
+
removeLabel
|
|
171
|
+
}) : /* @__PURE__ */ jsx("span", {
|
|
172
|
+
className: RelationField_module_default.none,
|
|
173
|
+
children: intl.formatMessage(messages.noRelation)
|
|
174
|
+
})
|
|
175
|
+
});
|
|
176
|
+
const comboLabel = typeof label === "string" ? label : props["aria-label"];
|
|
177
|
+
if (props.multiple === true) {
|
|
178
|
+
const { onChange } = props;
|
|
179
|
+
const set = (next) => onChange?.(next.length > 0 ? next : null);
|
|
180
|
+
return /* @__PURE__ */ jsx(Fieldset, {
|
|
181
|
+
...chrome,
|
|
182
|
+
description,
|
|
183
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
184
|
+
className: RelationField_module_default.multiple,
|
|
185
|
+
children: [selected.length > 0 ? /* @__PURE__ */ jsx(References, {
|
|
186
|
+
references: selected,
|
|
187
|
+
removeLabel,
|
|
188
|
+
onRemove: (reference_1) => set(selected.filter((entry) => entry.id !== reference_1.id))
|
|
189
|
+
}) : null, /* @__PURE__ */ jsx(ComboBox, {
|
|
190
|
+
"aria-label": comboLabel,
|
|
191
|
+
items: items.filter((item_0) => !selected.some((entry_0) => entry_0.id === item_0.id)).map((item_1) => ({
|
|
192
|
+
id: item_1.id,
|
|
193
|
+
label: item_1.label
|
|
194
|
+
})),
|
|
195
|
+
value: null,
|
|
196
|
+
inputValue: query ?? "",
|
|
197
|
+
onInputChange: setQuery,
|
|
198
|
+
onChange: (itemId) => {
|
|
199
|
+
if (itemId === CREATE_ID) {
|
|
200
|
+
createFrom((reference_2) => set([...selected, reference_2]));
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
const reference_3 = found.find((item_2) => item_2.id === itemId);
|
|
204
|
+
if (reference_3 !== void 0) {
|
|
205
|
+
set([...selected, reference_3]);
|
|
206
|
+
setQuery(null);
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
isLoading,
|
|
210
|
+
placeholder,
|
|
211
|
+
emptyMessage: intl.formatMessage(messages.noResults),
|
|
212
|
+
...onBlur !== void 0 ? { onBlur: () => onBlur() } : {},
|
|
213
|
+
...name !== void 0 ? { name } : {},
|
|
214
|
+
...id !== void 0 ? { id } : {},
|
|
215
|
+
...controlClassName !== void 0 ? { controlClassName } : {}
|
|
216
|
+
})]
|
|
217
|
+
})
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
const { onChange: onChange_0 } = props;
|
|
221
|
+
const current = selected[0] ?? null;
|
|
222
|
+
const shown = current !== null && !items.some((item_3) => item_3.id === current.id) ? [current, ...items] : items;
|
|
223
|
+
return /* @__PURE__ */ jsx(ComboBox, {
|
|
224
|
+
label,
|
|
225
|
+
description,
|
|
226
|
+
errors: allErrors,
|
|
227
|
+
isRequired: required,
|
|
228
|
+
className,
|
|
229
|
+
labelClassName,
|
|
230
|
+
descriptionClassName,
|
|
231
|
+
errorsClassName,
|
|
232
|
+
...controlClassName !== void 0 ? { controlClassName } : {},
|
|
233
|
+
...props["aria-label"] !== void 0 ? { "aria-label": props["aria-label"] } : {},
|
|
234
|
+
items: shown.map((item_4) => ({
|
|
235
|
+
id: item_4.id,
|
|
236
|
+
label: item_4.label
|
|
237
|
+
})),
|
|
238
|
+
value: current?.id ?? null,
|
|
239
|
+
inputValue: query ?? current?.label ?? "",
|
|
240
|
+
onInputChange: (text_1) => {
|
|
241
|
+
setQuery(text_1);
|
|
242
|
+
if (text_1 === "" && current !== null) onChange_0?.(null);
|
|
243
|
+
},
|
|
244
|
+
onChange: (itemId_0) => {
|
|
245
|
+
if (itemId_0 === CREATE_ID) {
|
|
246
|
+
createFrom((reference_4) => onChange_0?.(reference_4));
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
setQuery(null);
|
|
250
|
+
if (itemId_0 === null) return;
|
|
251
|
+
const reference_5 = shown.find((item_5) => item_5.id === itemId_0) ?? null;
|
|
252
|
+
if (reference_5?.id !== current?.id) onChange_0?.(reference_5);
|
|
253
|
+
},
|
|
254
|
+
isLoading,
|
|
255
|
+
placeholder,
|
|
256
|
+
emptyMessage: intl.formatMessage(messages.noResults),
|
|
257
|
+
...onBlur !== void 0 ? { onBlur: () => {
|
|
258
|
+
setQuery(null);
|
|
259
|
+
onBlur();
|
|
260
|
+
} } : { onBlur: () => setQuery(null) },
|
|
261
|
+
...name !== void 0 ? { name } : {},
|
|
262
|
+
...id !== void 0 ? { id } : {}
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
/** The `relation` type: `resource` and `multiple`. Items search the fields context's source. */
|
|
266
|
+
function RelationFieldEntry(props) {
|
|
267
|
+
const $ = c(15);
|
|
268
|
+
const { field } = props;
|
|
269
|
+
let t0;
|
|
270
|
+
if ($[0] !== props.value) {
|
|
271
|
+
t0 = toReferences(props.value);
|
|
272
|
+
$[0] = props.value;
|
|
273
|
+
$[1] = t0;
|
|
274
|
+
} else t0 = $[1];
|
|
275
|
+
const references = t0;
|
|
276
|
+
let t1;
|
|
277
|
+
if ($[2] !== props) {
|
|
278
|
+
t1 = getFieldProps(props);
|
|
279
|
+
$[2] = props;
|
|
280
|
+
$[3] = t1;
|
|
281
|
+
} else t1 = $[3];
|
|
282
|
+
const t2 = field.resource ?? "";
|
|
283
|
+
let t3;
|
|
284
|
+
if ($[4] !== t1 || $[5] !== t2) {
|
|
285
|
+
t3 = {
|
|
286
|
+
...t1,
|
|
287
|
+
resource: t2
|
|
288
|
+
};
|
|
289
|
+
$[4] = t1;
|
|
290
|
+
$[5] = t2;
|
|
291
|
+
$[6] = t3;
|
|
292
|
+
} else t3 = $[6];
|
|
293
|
+
const shared = t3;
|
|
294
|
+
if (field.multiple === true) {
|
|
295
|
+
let t4;
|
|
296
|
+
if ($[7] !== props.onChange || $[8] !== references || $[9] !== shared) {
|
|
297
|
+
t4 = /* @__PURE__ */ jsx(RelationField, {
|
|
298
|
+
...shared,
|
|
299
|
+
multiple: true,
|
|
300
|
+
value: references,
|
|
301
|
+
onChange: props.onChange
|
|
302
|
+
});
|
|
303
|
+
$[7] = props.onChange;
|
|
304
|
+
$[8] = references;
|
|
305
|
+
$[9] = shared;
|
|
306
|
+
$[10] = t4;
|
|
307
|
+
} else t4 = $[10];
|
|
308
|
+
return t4;
|
|
309
|
+
}
|
|
310
|
+
const t4 = references[0] ?? null;
|
|
311
|
+
let t5;
|
|
312
|
+
if ($[11] !== props.onChange || $[12] !== shared || $[13] !== t4) {
|
|
313
|
+
t5 = /* @__PURE__ */ jsx(RelationField, {
|
|
314
|
+
...shared,
|
|
315
|
+
value: t4,
|
|
316
|
+
onChange: props.onChange
|
|
317
|
+
});
|
|
318
|
+
$[11] = props.onChange;
|
|
319
|
+
$[12] = shared;
|
|
320
|
+
$[13] = t4;
|
|
321
|
+
$[14] = t5;
|
|
322
|
+
} else t5 = $[14];
|
|
323
|
+
return t5;
|
|
324
|
+
}
|
|
325
|
+
//#endregion
|
|
326
|
+
export { RelationField, RelationFieldEntry, useRelationSearch };
|
|
327
|
+
|
|
328
|
+
//# sourceMappingURL=RelationField.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RelationField.js","names":["X","text","reference","item","entry","onChange","itemId","references","_c","styles","_Fragment"],"sources":["../../src/relation/RelationField.tsx"],"sourcesContent":["import { X } from 'lucide-react';\nimport { useEffect, useState } from 'react';\n\nimport { ComboBox, Fieldset, IconButton, usePanneauIntl } from '@panneau/ui';\n\nimport { useFieldsContext } from '../shared/context';\nimport { cx } from '../shared/cx';\nimport { getFieldProps } from '../shared/entry';\nimport { messages } from '../shared/messages';\nimport {\n type RelationReference,\n type RelationSource,\n toReferences,\n useRelationReferences,\n} from '../shared/relation';\nimport type { FieldEntryProps, FieldProps } from '../shared/types';\nimport styles from './RelationField.module.css';\n\n/** The id of the \"Create “…”\" option of the picker. */\nconst CREATE_ID = '\\u0000create';\n\n/** Results of a search in a relation source, as it types. */\nexport function useRelationSearch(\n source: RelationSource | null,\n resource: string,\n query: string,\n { enabled = true, delay = 250 }: { enabled?: boolean; delay?: number } = {},\n): { items: RelationReference[]; isLoading: boolean } {\n const [state, setState] = useState<{\n key: string;\n items: RelationReference[];\n isLoading: boolean;\n }>({ key: '', items: [], isLoading: false });\n const key = `${resource}\\u0000${query}`;\n\n useEffect(() => {\n if (source === null || !enabled) {\n return undefined;\n }\n const controller = new AbortController();\n const timer = setTimeout(() => {\n setState((current) => ({ ...current, key, isLoading: true }));\n source\n .search(resource, query, { signal: controller.signal })\n .then((items) => {\n if (!controller.signal.aborted) {\n setState({ key, items, isLoading: false });\n }\n })\n .catch(() => {\n if (!controller.signal.aborted) {\n setState({ key, items: [], isLoading: false });\n }\n });\n }, delay);\n return () => {\n clearTimeout(timer);\n controller.abort();\n };\n }, [source, resource, query, key, enabled, delay]);\n\n return { items: state.items, isLoading: state.isLoading || state.key !== key };\n}\n\n/** Props of both single and multiple relation fields. */\nexport interface RelationFieldBaseProps extends Omit<FieldProps<never>, 'value' | 'onChange'> {\n /** Id of the related resource, passed to the source. */\n resource: string;\n /** Where to search. Defaults to the fields context's. Without one, the field is read-only. */\n source?: RelationSource | null;\n /**\n * Creates an item from the typed text, offered as \"Create “…”\" in the picker: it can open a\n * dialog, and resolves with the new reference, or `null` when nothing was created. Defaults to\n * the source's `create()`. `null` turns creating off.\n */\n onCreate?: ((text: string) => Promise<RelationReference | null>) | null;\n placeholder?: string;\n controlClassName?: string;\n}\n\nexport interface SingleRelationFieldProps extends RelationFieldBaseProps {\n multiple?: false;\n value?: RelationReference | null;\n onChange?: (value: RelationReference | null) => void;\n}\n\nexport interface MultipleRelationFieldProps extends RelationFieldBaseProps {\n multiple: true;\n value?: readonly RelationReference[] | null;\n /** Called with the references. An empty list is `null`. */\n onChange?: (value: RelationReference[] | null) => void;\n}\n\nexport type RelationFieldProps = SingleRelationFieldProps | MultipleRelationFieldProps;\n\nfunction References({\n references,\n onRemove,\n removeLabel,\n}: {\n references: readonly RelationReference[];\n onRemove?: (reference: RelationReference) => void;\n removeLabel: (reference: RelationReference) => string;\n}) {\n return (\n <ul className={cx(styles.selected, onRemove === undefined && styles.readOnly)}>\n {references.map((reference) => (\n <li key={reference.id} className={styles.reference}>\n <span className={styles.referenceLabel}>{reference.label}</span>\n {onRemove !== undefined ? (\n <IconButton\n icon={X}\n size=\"sm\"\n label={removeLabel(reference)}\n showTooltip={false}\n onPress={() => onRemove(reference)}\n />\n ) : null}\n </li>\n ))}\n </ul>\n );\n}\n\n/**\n * A reference to an item of another resource, or several with `multiple`, picked by searching a\n * `RelationSource`. Values are references (`{ id, label }`), as items carry them; plain ids get\n * their labels from the source's `resolve()`. When the source can `create()` (or with `onCreate`),\n * the picker offers to create an item from the typed text. Without a source, the field shows its\n * references and can't change them.\n */\nexport function RelationField(props: RelationFieldProps) {\n const intl = usePanneauIntl();\n const context = useFieldsContext();\n const source = props.source === undefined ? context.relationSource : props.source;\n const {\n resource,\n label,\n description,\n errors,\n disabled,\n readOnly,\n required,\n placeholder = intl.formatMessage(messages.search),\n onBlur,\n name,\n id,\n className,\n labelClassName,\n descriptionClassName,\n errorsClassName,\n controlClassName,\n } = props;\n const selected = useRelationReferences(source, resource, toReferences(props.value));\n const [query, setQuery] = useState<string | null>(null);\n const [creating, setCreating] = useState(false);\n const [createError, setCreateError] = useState<string | null>(null);\n const editable = source !== null && disabled !== true && readOnly !== true;\n const { items: found, isLoading: searching } = useRelationSearch(\n source,\n resource,\n query ?? '',\n { enabled: editable },\n );\n const sourceCreate = source?.create;\n const create =\n props.onCreate !== undefined\n ? props.onCreate\n : sourceCreate !== undefined && source?.canCreate?.(resource) !== false\n ? (text: string) => sourceCreate.call(source, resource, text)\n : null;\n const text = (query ?? '').trim();\n const offersCreate =\n create !== null &&\n text !== '' &&\n !searching &&\n ![...found, ...selected].some(\n (item) =>\n item.label.toLocaleLowerCase(intl.locale) === text.toLocaleLowerCase(intl.locale),\n );\n const items = offersCreate\n ? [\n ...found,\n { id: CREATE_ID, label: intl.formatMessage(messages.createRelation, { text }) },\n ]\n : found;\n const isLoading = searching || creating;\n const allErrors = createError !== null ? [...(errors ?? []), createError] : errors;\n /** Creates an item from the text, then adds its reference with `add`. */\n const createFrom = (add: (reference: RelationReference) => void) => {\n if (create === null) {\n return;\n }\n setCreating(true);\n setCreateError(null);\n create(text)\n .then((reference) => {\n if (reference !== null) {\n add(reference);\n setQuery(null);\n }\n })\n .catch(() =>\n setCreateError(intl.formatMessage(messages.createRelationFailed, { text })),\n )\n .finally(() => setCreating(false));\n };\n const removeLabel = (reference: RelationReference) =>\n `${intl.formatMessage(messages.remove)} ${reference.label}`;\n const chrome = {\n legend: label,\n errors: allErrors,\n isRequired: required,\n className,\n legendClassName: labelClassName,\n descriptionClassName,\n errorsClassName,\n };\n\n if (!editable) {\n return (\n <Fieldset\n {...chrome}\n description={\n source === null && disabled !== true && readOnly !== true ? (\n <>\n {description} {intl.formatMessage(messages.relationUnavailable)}\n </>\n ) : (\n description\n )\n }\n >\n {selected.length > 0 ? (\n <References references={selected} removeLabel={removeLabel} />\n ) : (\n <span className={styles.none}>{intl.formatMessage(messages.noRelation)}</span>\n )}\n </Fieldset>\n );\n }\n\n const comboLabel = typeof label === 'string' ? label : props['aria-label'];\n\n if (props.multiple === true) {\n const { onChange } = props;\n const set = (next: RelationReference[]) => onChange?.(next.length > 0 ? next : null);\n return (\n <Fieldset {...chrome} description={description}>\n <div className={styles.multiple}>\n {selected.length > 0 ? (\n <References\n references={selected}\n removeLabel={removeLabel}\n onRemove={(reference) =>\n set(selected.filter((entry) => entry.id !== reference.id))\n }\n />\n ) : null}\n <ComboBox\n aria-label={comboLabel}\n items={items\n .filter((item) => !selected.some((entry) => entry.id === item.id))\n .map((item) => ({ id: item.id, label: item.label }))}\n value={null}\n inputValue={query ?? ''}\n onInputChange={setQuery}\n onChange={(itemId) => {\n if (itemId === CREATE_ID) {\n createFrom((reference) => set([...selected, reference]));\n return;\n }\n const reference = found.find((item) => item.id === itemId);\n if (reference !== undefined) {\n set([...selected, reference]);\n setQuery(null);\n }\n }}\n isLoading={isLoading}\n placeholder={placeholder}\n emptyMessage={intl.formatMessage(messages.noResults)}\n {...(onBlur !== undefined ? { onBlur: () => onBlur() } : {})}\n {...(name !== undefined ? { name } : {})}\n {...(id !== undefined ? { id } : {})}\n {...(controlClassName !== undefined ? { controlClassName } : {})}\n />\n </div>\n </Fieldset>\n );\n }\n\n const { onChange } = props;\n const current = selected[0] ?? null;\n // The selected reference is among the items, so that the combo box knows its label.\n const shown =\n current !== null && !items.some((item) => item.id === current.id)\n ? [current, ...items]\n : items;\n return (\n <ComboBox\n label={label}\n description={description}\n errors={allErrors}\n isRequired={required}\n className={className}\n labelClassName={labelClassName}\n descriptionClassName={descriptionClassName}\n errorsClassName={errorsClassName}\n {...(controlClassName !== undefined ? { controlClassName } : {})}\n {...(props['aria-label'] !== undefined ? { 'aria-label': props['aria-label'] } : {})}\n items={shown.map((item) => ({ id: item.id, label: item.label }))}\n value={current?.id ?? null}\n inputValue={query ?? current?.label ?? ''}\n onInputChange={(text) => {\n setQuery(text);\n if (text === '' && current !== null) {\n onChange?.(null);\n }\n }}\n onChange={(itemId) => {\n if (itemId === CREATE_ID) {\n createFrom((reference) => onChange?.(reference));\n return;\n }\n setQuery(null);\n if (itemId === null) {\n return;\n }\n const reference = shown.find((item) => item.id === itemId) ?? null;\n if (reference?.id !== current?.id) {\n onChange?.(reference);\n }\n }}\n isLoading={isLoading}\n placeholder={placeholder}\n emptyMessage={intl.formatMessage(messages.noResults)}\n {...(onBlur !== undefined\n ? {\n onBlur: () => {\n setQuery(null);\n onBlur();\n },\n }\n : { onBlur: () => setQuery(null) })}\n {...(name !== undefined ? { name } : {})}\n {...(id !== undefined ? { id } : {})}\n />\n );\n}\n\n/** The `relation` type: `resource` and `multiple`. Items search the fields context's source. */\nexport function RelationFieldEntry(props: FieldEntryProps) {\n const { field } = props;\n const references = toReferences(props.value);\n const shared = { ...getFieldProps(props), resource: field.resource ?? '' };\n if (field.multiple === true) {\n return <RelationField {...shared} multiple value={references} onChange={props.onChange} />;\n }\n return <RelationField {...shared} value={references[0] ?? null} onChange={props.onChange} />;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import "./RelationField.css";
|
|
2
|
+
//#region src/relation/RelationField.module.css
|
|
3
|
+
var multiple = "panneau-multiple-u9IXr-";
|
|
4
|
+
var selected = "panneau-selected-PL7VcQ";
|
|
5
|
+
var reference = "panneau-reference-J8YpaW";
|
|
6
|
+
var readOnly = "panneau-readOnly-UunIK0";
|
|
7
|
+
var referenceLabel = "panneau-referenceLabel-ydQ0bU";
|
|
8
|
+
var none = "panneau-none-niMk7v";
|
|
9
|
+
var RelationField_module_default = {
|
|
10
|
+
multiple,
|
|
11
|
+
selected,
|
|
12
|
+
reference,
|
|
13
|
+
readOnly,
|
|
14
|
+
referenceLabel,
|
|
15
|
+
none
|
|
16
|
+
};
|
|
17
|
+
//#endregion
|
|
18
|
+
export { RelationField_module_default as default, multiple, none, readOnly, reference, referenceLabel, selected };
|
|
19
|
+
|
|
20
|
+
//# sourceMappingURL=RelationField.module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RelationField.module.js","names":[],"sources":["../../src/relation/RelationField.module.css"],"sourcesContent":[".multiple {\n display: flex;\n flex-direction: column;\n gap: var(--panneau-space-2);\n}\n\n.selected {\n display: flex;\n flex-wrap: wrap;\n gap: var(--panneau-space-1) var(--panneau-space-2);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.reference {\n display: inline-flex;\n align-items: center;\n gap: var(--panneau-space-1);\n min-height: var(--panneau-control-height-sm);\n max-width: 100%;\n padding-inline: var(--panneau-space-3) var(--panneau-space-1);\n font-size: var(--panneau-font-size-sm);\n background-color: var(--panneau-color-surface-sunken);\n border: var(--panneau-border-width) solid var(--panneau-color-border);\n border-radius: var(--panneau-radius-full);\n}\n\n.reference:only-child,\n.readOnly .reference {\n padding-inline-end: var(--panneau-space-3);\n}\n\n.referenceLabel {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.none {\n font-size: var(--panneau-font-size-md);\n color: var(--panneau-color-text-muted);\n}\n"],"mappings":""}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { type MultipleRelationFieldProps, type RelationFieldBaseProps, RelationField, RelationFieldEntry, type RelationFieldProps, type SingleRelationFieldProps, useRelationSearch, } from './RelationField';
|
|
2
|
+
export { type RelationListAdapter, type RelationReference, type RelationSource, type RelationSourceOptions, createRelationSource, useRelationReferences, } from '../shared/relation';
|
|
3
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/relation/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,KAAK,0BAA0B,EAC/B,KAAK,sBAAsB,EAC3B,aAAa,EACb,kBAAkB,EAClB,KAAK,kBAAkB,EACvB,KAAK,wBAAwB,EAC7B,iBAAiB,GACpB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACH,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,qBAAqB,EAC1B,oBAAoB,EACpB,qBAAqB,GACxB,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { createRelationSource, useRelationReferences } from "../shared/relation.js";
|
|
2
|
+
import { RelationField, RelationFieldEntry, useRelationSearch } from "./RelationField.js";
|
|
3
|
+
export { RelationField, RelationFieldEntry, createRelationSource, useRelationReferences, useRelationSearch };
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
.panneau-items-B5uTq4 {
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-direction: column;
|
|
4
|
+
gap: var(--panneau-space-3);
|
|
5
|
+
margin: 0;
|
|
6
|
+
padding: 0;
|
|
7
|
+
list-style: none;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.panneau-item-cNAgol {
|
|
11
|
+
display: flex;
|
|
12
|
+
flex-direction: column;
|
|
13
|
+
min-width: 0;
|
|
14
|
+
background-color: var(--panneau-color-surface);
|
|
15
|
+
border: var(--panneau-border-width) solid var(--panneau-color-border);
|
|
16
|
+
border-radius: var(--panneau-radius-md);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.panneau-header-QLqgvh {
|
|
20
|
+
display: flex;
|
|
21
|
+
align-items: center;
|
|
22
|
+
gap: var(--panneau-space-2);
|
|
23
|
+
min-height: var(--panneau-control-height);
|
|
24
|
+
padding: var(--panneau-space-1) var(--panneau-space-1) var(--panneau-space-1)
|
|
25
|
+
var(--panneau-space-3);
|
|
26
|
+
background-color: var(--panneau-color-surface-sunken);
|
|
27
|
+
border-bottom: var(--panneau-border-width) solid var(--panneau-color-border);
|
|
28
|
+
border-start-start-radius: inherit;
|
|
29
|
+
border-start-end-radius: inherit;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.panneau-title-0eDHTu {
|
|
33
|
+
flex: 1 1 auto;
|
|
34
|
+
min-width: 0;
|
|
35
|
+
overflow: hidden;
|
|
36
|
+
font-size: var(--panneau-font-size-sm);
|
|
37
|
+
font-weight: var(--panneau-font-weight-medium);
|
|
38
|
+
text-overflow: ellipsis;
|
|
39
|
+
white-space: nowrap;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.panneau-index-IrOBUU {
|
|
43
|
+
margin-inline-end: var(--panneau-space-2);
|
|
44
|
+
font-variant-numeric: tabular-nums;
|
|
45
|
+
color: var(--panneau-color-text-muted);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.panneau-tools-zbGiq2 {
|
|
49
|
+
display: flex;
|
|
50
|
+
flex: 0 0 auto;
|
|
51
|
+
gap: var(--panneau-space-1);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.panneau-body-iQtLK9 {
|
|
55
|
+
display: flex;
|
|
56
|
+
flex-direction: column;
|
|
57
|
+
gap: var(--panneau-space-4);
|
|
58
|
+
padding: var(--panneau-space-4);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.panneau-empty-MST5Cj {
|
|
62
|
+
padding: var(--panneau-space-3);
|
|
63
|
+
font-size: var(--panneau-font-size-sm);
|
|
64
|
+
color: var(--panneau-color-text-muted);
|
|
65
|
+
text-align: center;
|
|
66
|
+
border: var(--panneau-border-width) dashed var(--panneau-color-border-control);
|
|
67
|
+
border-radius: var(--panneau-radius-md);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.panneau-footer-5jeHXH {
|
|
71
|
+
display: flex;
|
|
72
|
+
flex-wrap: wrap;
|
|
73
|
+
gap: var(--panneau-space-2);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
@media (max-width: 30rem) {
|
|
77
|
+
.panneau-body-iQtLK9 {
|
|
78
|
+
padding: var(--panneau-space-3);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { BlockType, Field } from '@panneau/protocol';
|
|
2
|
+
import type { FieldEntryProps, FieldProps } from '../shared/types';
|
|
3
|
+
/** An item of a repeater. Typed blocks have their type in `type`. */
|
|
4
|
+
export type RepeaterItem = Record<string, unknown>;
|
|
5
|
+
export interface RepeaterFieldProps extends FieldProps<RepeaterItem[]> {
|
|
6
|
+
/** The fields of each item. */
|
|
7
|
+
fields?: readonly Field[];
|
|
8
|
+
/** Typed blocks: each item has a `type`, and the fields of that type. */
|
|
9
|
+
types?: readonly BlockType[];
|
|
10
|
+
/** Dot path of the list, the prefix of its fields' paths (`blocks.2.body`). Defaults to `name`. */
|
|
11
|
+
path?: string;
|
|
12
|
+
/** Fewest items: items can't be removed below it. */
|
|
13
|
+
min?: number;
|
|
14
|
+
/** Most items: no item can be added above it. */
|
|
15
|
+
max?: number;
|
|
16
|
+
itemClassName?: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* A list of items, each with the same fields, or typed blocks with the fields of their type. Items
|
|
20
|
+
* can be added, moved and removed. Each field renders at the path `<list>.<index>.<field>`. An
|
|
21
|
+
* empty list is `null`.
|
|
22
|
+
*/
|
|
23
|
+
export declare function RepeaterField({ fields, types, path, name, value, onChange, onBlur, label, description, errors, disabled, readOnly, required, min, max, className, labelClassName, descriptionClassName, errorsClassName, itemClassName, }: RepeaterFieldProps): import("react").JSX.Element;
|
|
24
|
+
/**
|
|
25
|
+
* The `repeater` type: `fields`, or `types` for typed blocks, with `min` and `max` items from its
|
|
26
|
+
* rules.
|
|
27
|
+
*/
|
|
28
|
+
export declare function RepeaterFieldEntry(props: FieldEntryProps): import("react").JSX.Element;
|
|
29
|
+
//# sourceMappingURL=RepeaterField.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RepeaterField.d.ts","sourceRoot":"","sources":["../../src/repeater/RepeaterField.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAe1D,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAGnE,qEAAqE;AACrE,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEnD,MAAM,WAAW,kBAAmB,SAAQ,UAAU,CAAC,YAAY,EAAE,CAAC;IAClE,+BAA+B;IAC/B,MAAM,CAAC,EAAE,SAAS,KAAK,EAAE,CAAC;IAC1B,yEAAyE;IACzE,KAAK,CAAC,EAAE,SAAS,SAAS,EAAE,CAAC;IAC7B,mGAAmG;IACnG,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,qDAAqD;IACrD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,iDAAiD;IACjD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B;AAUD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,EAC1B,MAAW,EACX,KAAK,EACL,IAAI,EACJ,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,MAAM,EACN,KAAK,EACL,WAAW,EACX,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,GAAO,EACP,GAAG,EACH,SAAS,EACT,cAAc,EACd,oBAAoB,EACpB,eAAe,EACf,aAAa,GAChB,EAAE,kBAAkB,+BAuJpB;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,eAAe,+BAwBxD"}
|