@realiizlabs/admin 0.11.0 → 0.11.2
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/auth-ui/index.cjs +12 -0
- package/dist/auth-ui/index.cjs.map +1 -1
- package/dist/auth-ui/index.js +1 -1
- package/dist/{chunk-FTD4WE3V.js → chunk-2GSYBARR.js} +14 -2
- package/dist/chunk-2GSYBARR.js.map +1 -0
- package/dist/forms-ui/index.cjs +148 -4
- package/dist/forms-ui/index.cjs.map +1 -1
- package/dist/forms-ui/index.d.cts +17 -1
- package/dist/forms-ui/index.d.ts +17 -1
- package/dist/forms-ui/index.js +139 -8
- package/dist/forms-ui/index.js.map +1 -1
- package/dist/shell/index.cjs +5 -3
- package/dist/shell/index.cjs.map +1 -1
- package/dist/shell/index.d.cts +4 -2
- package/dist/shell/index.d.ts +4 -2
- package/dist/shell/index.js +5 -3
- package/dist/shell/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-FTD4WE3V.js.map +0 -1
|
@@ -189,6 +189,22 @@ interface ImageInputProps {
|
|
|
189
189
|
}
|
|
190
190
|
declare function ImageInput(p: ImageInputProps): react.JSX.Element;
|
|
191
191
|
|
|
192
|
+
interface SelectInputProps {
|
|
193
|
+
id: string;
|
|
194
|
+
name: string;
|
|
195
|
+
value: string;
|
|
196
|
+
options: string[];
|
|
197
|
+
/** Optional display names, keyed by value. */
|
|
198
|
+
labels?: Record<string, string>;
|
|
199
|
+
/** Adds a "—" choice at the top that sets the value to "". */
|
|
200
|
+
allowEmpty?: boolean;
|
|
201
|
+
invalid?: boolean;
|
|
202
|
+
disabled?: boolean;
|
|
203
|
+
onChange: (v: string) => void;
|
|
204
|
+
onBlur?: () => void;
|
|
205
|
+
}
|
|
206
|
+
declare function SelectInput(p: SelectInputProps): react.JSX.Element;
|
|
207
|
+
|
|
192
208
|
/**
|
|
193
209
|
* ChipsInput — tags as chips. Enter or comma adds, × or Backspace-on-empty
|
|
194
210
|
* removes. The value is a string[]; the schema's length/regex rules still run
|
|
@@ -206,4 +222,4 @@ declare function ChipsInput({ id, name, value, onChange, onBlur, placeholder, in
|
|
|
206
222
|
max?: number;
|
|
207
223
|
}): react.JSX.Element;
|
|
208
224
|
|
|
209
|
-
export { ChipsInput, ContentForm, type ContentFormProps, type ContentFormSubmission, IMAGE_HINT, ImageInput, type ImageInputProps, type LabelRenderer, LengthGauge, MarkdownEditor, type MarkdownEditorProps, type PickImage, type PickResult, type PickedImage, type SubmittedImages, TOOLS, slugify };
|
|
225
|
+
export { ChipsInput, ContentForm, type ContentFormProps, type ContentFormSubmission, IMAGE_HINT, ImageInput, type ImageInputProps, type LabelRenderer, LengthGauge, MarkdownEditor, type MarkdownEditorProps, type PickImage, type PickResult, type PickedImage, SelectInput, type SelectInputProps, type SubmittedImages, TOOLS, slugify };
|
package/dist/forms-ui/index.d.ts
CHANGED
|
@@ -189,6 +189,22 @@ interface ImageInputProps {
|
|
|
189
189
|
}
|
|
190
190
|
declare function ImageInput(p: ImageInputProps): react.JSX.Element;
|
|
191
191
|
|
|
192
|
+
interface SelectInputProps {
|
|
193
|
+
id: string;
|
|
194
|
+
name: string;
|
|
195
|
+
value: string;
|
|
196
|
+
options: string[];
|
|
197
|
+
/** Optional display names, keyed by value. */
|
|
198
|
+
labels?: Record<string, string>;
|
|
199
|
+
/** Adds a "—" choice at the top that sets the value to "". */
|
|
200
|
+
allowEmpty?: boolean;
|
|
201
|
+
invalid?: boolean;
|
|
202
|
+
disabled?: boolean;
|
|
203
|
+
onChange: (v: string) => void;
|
|
204
|
+
onBlur?: () => void;
|
|
205
|
+
}
|
|
206
|
+
declare function SelectInput(p: SelectInputProps): react.JSX.Element;
|
|
207
|
+
|
|
192
208
|
/**
|
|
193
209
|
* ChipsInput — tags as chips. Enter or comma adds, × or Backspace-on-empty
|
|
194
210
|
* removes. The value is a string[]; the schema's length/regex rules still run
|
|
@@ -206,4 +222,4 @@ declare function ChipsInput({ id, name, value, onChange, onBlur, placeholder, in
|
|
|
206
222
|
max?: number;
|
|
207
223
|
}): react.JSX.Element;
|
|
208
224
|
|
|
209
|
-
export { ChipsInput, ContentForm, type ContentFormProps, type ContentFormSubmission, IMAGE_HINT, ImageInput, type ImageInputProps, type LabelRenderer, LengthGauge, MarkdownEditor, type MarkdownEditorProps, type PickImage, type PickResult, type PickedImage, type SubmittedImages, TOOLS, slugify };
|
|
225
|
+
export { ChipsInput, ContentForm, type ContentFormProps, type ContentFormSubmission, IMAGE_HINT, ImageInput, type ImageInputProps, type LabelRenderer, LengthGauge, MarkdownEditor, type MarkdownEditorProps, type PickImage, type PickResult, type PickedImage, SelectInput, type SelectInputProps, type SubmittedImages, TOOLS, slugify };
|
package/dist/forms-ui/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { walkSchema } from '../chunk-JLR5K6RP.js';
|
|
3
|
-
import { FORM_CSS } from '../chunk-
|
|
4
|
-
import { useState, useRef,
|
|
2
|
+
import { walkSchema, titlecase } from '../chunk-JLR5K6RP.js';
|
|
3
|
+
import { FORM_CSS } from '../chunk-2GSYBARR.js';
|
|
4
|
+
import { useState, useRef, useId, useEffect, useCallback, useMemo } from 'react';
|
|
5
5
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
6
6
|
|
|
7
7
|
function ChipsInput({ id, name, value, onChange, onBlur, placeholder, invalid, max }) {
|
|
@@ -48,6 +48,128 @@ function ChipsInput({ id, name, value, onChange, onBlur, placeholder, invalid, m
|
|
|
48
48
|
] })
|
|
49
49
|
] });
|
|
50
50
|
}
|
|
51
|
+
function labelFor(value, labels) {
|
|
52
|
+
if (labels?.[value]) return labels[value];
|
|
53
|
+
return value ? titlecase(value) : "\u2014";
|
|
54
|
+
}
|
|
55
|
+
function SelectInput(p) {
|
|
56
|
+
const [open, setOpen] = useState(false);
|
|
57
|
+
const [active, setActive] = useState(0);
|
|
58
|
+
const wrap = useRef(null);
|
|
59
|
+
const list = useRef(null);
|
|
60
|
+
const listId = useId();
|
|
61
|
+
const choices = p.allowEmpty ? ["", ...p.options] : p.options;
|
|
62
|
+
const latest = useRef({ choices, value: p.value });
|
|
63
|
+
latest.current = { choices, value: p.value };
|
|
64
|
+
useEffect(() => {
|
|
65
|
+
if (!open) return;
|
|
66
|
+
setActive(Math.max(0, latest.current.choices.indexOf(latest.current.value)));
|
|
67
|
+
const onDoc = (e) => {
|
|
68
|
+
if (!wrap.current?.contains(e.target)) close();
|
|
69
|
+
};
|
|
70
|
+
document.addEventListener("mousedown", onDoc);
|
|
71
|
+
return () => document.removeEventListener("mousedown", onDoc);
|
|
72
|
+
}, [open]);
|
|
73
|
+
useEffect(() => {
|
|
74
|
+
if (!open) return;
|
|
75
|
+
list.current?.querySelectorAll("[role=option]")[active]?.scrollIntoView?.({ block: "nearest" });
|
|
76
|
+
}, [open, active]);
|
|
77
|
+
const close = () => {
|
|
78
|
+
setOpen(false);
|
|
79
|
+
p.onBlur?.();
|
|
80
|
+
};
|
|
81
|
+
const pick = (v) => {
|
|
82
|
+
if (v !== p.value) p.onChange(v);
|
|
83
|
+
close();
|
|
84
|
+
};
|
|
85
|
+
const onKey = (e) => {
|
|
86
|
+
if (!open) {
|
|
87
|
+
if (e.key === "ArrowDown" || e.key === "ArrowUp" || e.key === "Enter" || e.key === " ") {
|
|
88
|
+
e.preventDefault();
|
|
89
|
+
setOpen(true);
|
|
90
|
+
}
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
switch (e.key) {
|
|
94
|
+
case "ArrowDown":
|
|
95
|
+
e.preventDefault();
|
|
96
|
+
setActive((i) => Math.min(choices.length - 1, i + 1));
|
|
97
|
+
break;
|
|
98
|
+
case "ArrowUp":
|
|
99
|
+
e.preventDefault();
|
|
100
|
+
setActive((i) => Math.max(0, i - 1));
|
|
101
|
+
break;
|
|
102
|
+
case "Home":
|
|
103
|
+
e.preventDefault();
|
|
104
|
+
setActive(0);
|
|
105
|
+
break;
|
|
106
|
+
case "End":
|
|
107
|
+
e.preventDefault();
|
|
108
|
+
setActive(choices.length - 1);
|
|
109
|
+
break;
|
|
110
|
+
case "Enter":
|
|
111
|
+
case " ":
|
|
112
|
+
e.preventDefault();
|
|
113
|
+
pick(choices[active] ?? "");
|
|
114
|
+
break;
|
|
115
|
+
case "Escape":
|
|
116
|
+
e.preventDefault();
|
|
117
|
+
close();
|
|
118
|
+
break;
|
|
119
|
+
case "Tab":
|
|
120
|
+
close();
|
|
121
|
+
break;
|
|
122
|
+
default: {
|
|
123
|
+
if (e.key.length === 1 && /\S/.test(e.key)) {
|
|
124
|
+
const k = e.key.toLowerCase();
|
|
125
|
+
const idx = choices.findIndex((c) => labelFor(c, p.labels).toLowerCase().startsWith(k));
|
|
126
|
+
if (idx >= 0) setActive(idx);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
const cls = ["realiiz-form__control", "realiiz-select__btn", p.invalid && "realiiz-form__control--invalid", open && "realiiz-select__btn--open"].filter(Boolean).join(" ");
|
|
132
|
+
return /* @__PURE__ */ jsxs("div", { ref: wrap, className: "realiiz-select", onKeyDown: onKey, children: [
|
|
133
|
+
/* @__PURE__ */ jsx("input", { type: "hidden", name: p.name, value: p.value, readOnly: true }),
|
|
134
|
+
/* @__PURE__ */ jsxs(
|
|
135
|
+
"button",
|
|
136
|
+
{
|
|
137
|
+
type: "button",
|
|
138
|
+
id: p.id,
|
|
139
|
+
className: cls,
|
|
140
|
+
role: "combobox",
|
|
141
|
+
"aria-haspopup": "listbox",
|
|
142
|
+
"aria-expanded": open,
|
|
143
|
+
"aria-controls": listId,
|
|
144
|
+
"aria-invalid": p.invalid || void 0,
|
|
145
|
+
"aria-describedby": p.invalid ? `${p.id}-error` : void 0,
|
|
146
|
+
disabled: p.disabled,
|
|
147
|
+
onClick: () => open ? close() : setOpen(true),
|
|
148
|
+
children: [
|
|
149
|
+
/* @__PURE__ */ jsx("span", { className: p.value ? void 0 : "realiiz-select__placeholder", children: labelFor(p.value, p.labels) }),
|
|
150
|
+
/* @__PURE__ */ jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "M6 9l6 6 6-6" }) })
|
|
151
|
+
]
|
|
152
|
+
}
|
|
153
|
+
),
|
|
154
|
+
open && /* @__PURE__ */ jsx("ul", { ref: list, id: listId, className: "realiiz-select__menu", role: "listbox", "aria-labelledby": p.id, tabIndex: -1, children: choices.map((c, i) => /* @__PURE__ */ jsxs(
|
|
155
|
+
"li",
|
|
156
|
+
{
|
|
157
|
+
role: "option",
|
|
158
|
+
"aria-selected": c === p.value,
|
|
159
|
+
"data-value": c,
|
|
160
|
+
className: ["realiiz-select__item", i === active && "realiiz-select__item--active", c === p.value && "realiiz-select__item--selected"].filter(Boolean).join(" "),
|
|
161
|
+
onMouseEnter: () => setActive(i),
|
|
162
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
163
|
+
onClick: () => pick(c),
|
|
164
|
+
children: [
|
|
165
|
+
/* @__PURE__ */ jsx("span", { className: "realiiz-select__check", "aria-hidden": "true", children: c === p.value ? "\u2713" : "" }),
|
|
166
|
+
/* @__PURE__ */ jsx("span", { children: labelFor(c, p.labels) })
|
|
167
|
+
]
|
|
168
|
+
},
|
|
169
|
+
c || "__empty"
|
|
170
|
+
)) })
|
|
171
|
+
] });
|
|
172
|
+
}
|
|
51
173
|
function Control(p) {
|
|
52
174
|
const cls = ["realiiz-form__control", p.invalid && "realiiz-form__control--invalid"].filter(Boolean).join(" ");
|
|
53
175
|
const common = {
|
|
@@ -62,10 +184,19 @@ function Control(p) {
|
|
|
62
184
|
return /* @__PURE__ */ jsx("div", { className: cls, "aria-busy": "true", style: { color: "var(--_muted)" }, children: "Loading options\u2026" });
|
|
63
185
|
}
|
|
64
186
|
if (p.options || p.spec.input === "select") {
|
|
65
|
-
return /* @__PURE__ */
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
187
|
+
return /* @__PURE__ */ jsx(
|
|
188
|
+
SelectInput,
|
|
189
|
+
{
|
|
190
|
+
id: p.id,
|
|
191
|
+
name: p.spec.name,
|
|
192
|
+
value: str,
|
|
193
|
+
options: p.options ?? [],
|
|
194
|
+
allowEmpty: !p.spec.required,
|
|
195
|
+
invalid: p.invalid,
|
|
196
|
+
onChange: p.onChange,
|
|
197
|
+
onBlur: p.onBlur
|
|
198
|
+
}
|
|
199
|
+
);
|
|
69
200
|
}
|
|
70
201
|
switch (p.spec.input) {
|
|
71
202
|
case "textarea":
|
|
@@ -1173,6 +1304,6 @@ function sameValue(a, b) {
|
|
|
1173
1304
|
return a === b;
|
|
1174
1305
|
}
|
|
1175
1306
|
|
|
1176
|
-
export { ChipsInput, ContentForm, IMAGE_HINT, ImageInput, LengthGauge, MarkdownEditor, TOOLS, slugify };
|
|
1307
|
+
export { ChipsInput, ContentForm, IMAGE_HINT, ImageInput, LengthGauge, MarkdownEditor, SelectInput, TOOLS, slugify };
|
|
1177
1308
|
//# sourceMappingURL=index.js.map
|
|
1178
1309
|
//# sourceMappingURL=index.js.map
|