@camstack/ui-library 1.2.331 → 1.2.332
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/composites/grouped-tile-picker.d.ts +8 -11
- package/dist/index.cjs +58 -22
- package/dist/index.js +58 -22
- package/package.json +1 -1
|
@@ -1,20 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
* `GroupedTilePicker` — choose ONE "type of thing" from tiles grouped by who
|
|
3
|
-
* provides it (an AI profile kind, a notification-target kind…): an uppercase
|
|
4
|
-
* group label, then a grid of icon + label tiles. The pre-modal of a
|
|
5
|
-
* create-flow whose form depends on the choice.
|
|
6
|
-
*
|
|
7
|
-
* The tile is deliberately not a `Button`: a vertical icon-over-label card in
|
|
8
|
-
* a grid, which toolbar-button chrome fights. One place owns that look so the
|
|
9
|
-
* pickers stay identical.
|
|
10
|
-
*/
|
|
11
|
-
import type { JSX, ReactNode } from "react";
|
|
1
|
+
import { type JSX, type ReactNode } from "react";
|
|
12
2
|
export interface TilePickerTile {
|
|
13
3
|
/** Unique within the picker; handed back to `onPick`. */
|
|
14
4
|
readonly key: string;
|
|
15
5
|
readonly label: string;
|
|
16
6
|
readonly icon: ReactNode;
|
|
17
7
|
readonly testId?: string;
|
|
8
|
+
/**
|
|
9
|
+
* Extra facts for the tile (supported operations, a shared-capability list).
|
|
10
|
+
* A tap target beside the name — it does not choose the tile.
|
|
11
|
+
*/
|
|
12
|
+
readonly detail?: ReactNode;
|
|
13
|
+
/** Accessible name of the detail control. Required when `detail` is set. */
|
|
14
|
+
readonly detailLabel?: string;
|
|
18
15
|
}
|
|
19
16
|
export interface TilePickerGroup {
|
|
20
17
|
readonly id: string;
|
package/dist/index.cjs
CHANGED
|
@@ -14504,6 +14504,9 @@ function AccountSignInField({ field, values, disabled, onAction, onChangeMany })
|
|
|
14504
14504
|
if (Object.keys(patch).length > 0) onChangeMany?.(patch);
|
|
14505
14505
|
const nextChoices = choicesOf(result["choices"]);
|
|
14506
14506
|
setChoices(nextChoices.length > 1 ? nextChoices : []);
|
|
14507
|
+
const picked = typeof result["gatewayId"] === "string" && result["gatewayId"].length > 0;
|
|
14508
|
+
const summary = typeof result["summary"] === "string" ? result["summary"] : null;
|
|
14509
|
+
if (summary !== null && !picked && nextChoices.length < 2) setError(summary);
|
|
14507
14510
|
setPhase("idle");
|
|
14508
14511
|
setPaste("");
|
|
14509
14512
|
setAttemptId(null);
|
|
@@ -31013,13 +31016,13 @@ function InfoBox({ field }) {
|
|
|
31013
31016
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
31014
31017
|
className: `rounded-md border-l-4 px-3 py-2.5 ${styles.border} ${styles.bg}`,
|
|
31015
31018
|
children: [field.label && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
31016
|
-
className: `text-xs font-semibold mb-0.5 ${styles.text}
|
|
31019
|
+
className: field.content.length > 0 ? `text-xs font-semibold mb-0.5 ${styles.text}` : "text-xs text-foreground-subtle leading-relaxed whitespace-pre-line break-words",
|
|
31017
31020
|
children: field.label
|
|
31018
31021
|
}), isHtml ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
31019
31022
|
className: "text-xs text-foreground-subtle leading-relaxed info-html-content",
|
|
31020
31023
|
dangerouslySetInnerHTML: { __html: sanitizeInfoHtml(field.content) }
|
|
31021
|
-
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
31022
|
-
className: "text-xs text-foreground-subtle leading-relaxed whitespace-pre-line",
|
|
31024
|
+
}) : field.content.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
31025
|
+
className: "text-xs text-foreground-subtle leading-relaxed whitespace-pre-line break-words",
|
|
31023
31026
|
children: field.content
|
|
31024
31027
|
})]
|
|
31025
31028
|
})
|
|
@@ -61148,28 +61151,61 @@ function FormField$1({ label, description, error, required, children, orientatio
|
|
|
61148
61151
|
}
|
|
61149
61152
|
//#endregion
|
|
61150
61153
|
//#region src/composites/grouped-tile-picker.tsx
|
|
61154
|
+
/**
|
|
61155
|
+
* `GroupedTilePicker` — choose ONE "type of thing" from tiles grouped by who
|
|
61156
|
+
* provides it (an AI profile kind, a notification-target kind…): an uppercase
|
|
61157
|
+
* group label, then a grid of icon + label tiles. The pre-modal of a
|
|
61158
|
+
* create-flow whose form depends on the choice.
|
|
61159
|
+
*
|
|
61160
|
+
* The tile is deliberately not a `Button`: a vertical icon-over-label card in
|
|
61161
|
+
* a grid, which toolbar-button chrome fights. One place owns that look so the
|
|
61162
|
+
* pickers stay identical.
|
|
61163
|
+
*/
|
|
61151
61164
|
function GroupedTilePicker({ groups, onPick, emptyMessage }) {
|
|
61165
|
+
const [openKey, setOpenKey] = (0, react$1.useState)(null);
|
|
61166
|
+
const openTile = openKey === null ? null : groups.flatMap((group) => group.tiles).find((tile) => tile.key === openKey) ?? null;
|
|
61152
61167
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
61153
61168
|
className: "space-y-4",
|
|
61154
|
-
children: [
|
|
61155
|
-
|
|
61156
|
-
|
|
61157
|
-
|
|
61158
|
-
|
|
61159
|
-
children:
|
|
61160
|
-
|
|
61161
|
-
|
|
61162
|
-
|
|
61163
|
-
|
|
61164
|
-
|
|
61165
|
-
|
|
61166
|
-
|
|
61167
|
-
|
|
61168
|
-
|
|
61169
|
-
|
|
61170
|
-
|
|
61171
|
-
|
|
61172
|
-
|
|
61169
|
+
children: [
|
|
61170
|
+
groups.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
61171
|
+
className: "text-xs text-foreground-subtle",
|
|
61172
|
+
children: emptyMessage
|
|
61173
|
+
}),
|
|
61174
|
+
groups.map((group) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
61175
|
+
className: "mb-1.5 text-[10px] font-semibold uppercase tracking-wider text-foreground-subtle",
|
|
61176
|
+
children: group.label
|
|
61177
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
61178
|
+
className: "grid grid-cols-2 gap-2 sm:grid-cols-3",
|
|
61179
|
+
children: group.tiles.map((tile) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
61180
|
+
className: "relative",
|
|
61181
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
61182
|
+
type: "button",
|
|
61183
|
+
"data-testid": tile.testId,
|
|
61184
|
+
onClick: () => onPick(tile.key),
|
|
61185
|
+
className: "flex h-full w-full flex-col items-center gap-1.5 rounded-lg border border-border bg-surface px-3 py-3 text-xs transition-colors hover:border-primary/50 hover:bg-surface-hover",
|
|
61186
|
+
children: [tile.icon, /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
61187
|
+
className: "text-center font-medium text-foreground",
|
|
61188
|
+
children: tile.label
|
|
61189
|
+
})]
|
|
61190
|
+
}), tile.detail !== void 0 && tile.detailLabel !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
61191
|
+
className: "absolute top-1 right-1",
|
|
61192
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconButton, {
|
|
61193
|
+
type: "button",
|
|
61194
|
+
variant: "ghost",
|
|
61195
|
+
size: "sm",
|
|
61196
|
+
icon: Info,
|
|
61197
|
+
"aria-label": tile.detailLabel,
|
|
61198
|
+
onClick: () => setOpenKey((current) => current === tile.key ? null : tile.key)
|
|
61199
|
+
})
|
|
61200
|
+
})]
|
|
61201
|
+
}, tile.key))
|
|
61202
|
+
})] }, group.id)),
|
|
61203
|
+
openTile?.detail !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BottomSheet, {
|
|
61204
|
+
open: true,
|
|
61205
|
+
onClose: () => setOpenKey(null),
|
|
61206
|
+
children: openTile.detail
|
|
61207
|
+
})
|
|
61208
|
+
]
|
|
61173
61209
|
});
|
|
61174
61210
|
}
|
|
61175
61211
|
//#endregion
|
package/dist/index.js
CHANGED
|
@@ -14480,6 +14480,9 @@ function AccountSignInField({ field, values, disabled, onAction, onChangeMany })
|
|
|
14480
14480
|
if (Object.keys(patch).length > 0) onChangeMany?.(patch);
|
|
14481
14481
|
const nextChoices = choicesOf(result["choices"]);
|
|
14482
14482
|
setChoices(nextChoices.length > 1 ? nextChoices : []);
|
|
14483
|
+
const picked = typeof result["gatewayId"] === "string" && result["gatewayId"].length > 0;
|
|
14484
|
+
const summary = typeof result["summary"] === "string" ? result["summary"] : null;
|
|
14485
|
+
if (summary !== null && !picked && nextChoices.length < 2) setError(summary);
|
|
14483
14486
|
setPhase("idle");
|
|
14484
14487
|
setPaste("");
|
|
14485
14488
|
setAttemptId(null);
|
|
@@ -30989,13 +30992,13 @@ function InfoBox({ field }) {
|
|
|
30989
30992
|
children: /* @__PURE__ */ jsxs("div", {
|
|
30990
30993
|
className: `rounded-md border-l-4 px-3 py-2.5 ${styles.border} ${styles.bg}`,
|
|
30991
30994
|
children: [field.label && /* @__PURE__ */ jsx("p", {
|
|
30992
|
-
className: `text-xs font-semibold mb-0.5 ${styles.text}
|
|
30995
|
+
className: field.content.length > 0 ? `text-xs font-semibold mb-0.5 ${styles.text}` : "text-xs text-foreground-subtle leading-relaxed whitespace-pre-line break-words",
|
|
30993
30996
|
children: field.label
|
|
30994
30997
|
}), isHtml ? /* @__PURE__ */ jsx("div", {
|
|
30995
30998
|
className: "text-xs text-foreground-subtle leading-relaxed info-html-content",
|
|
30996
30999
|
dangerouslySetInnerHTML: { __html: sanitizeInfoHtml(field.content) }
|
|
30997
|
-
}) : /* @__PURE__ */ jsx("p", {
|
|
30998
|
-
className: "text-xs text-foreground-subtle leading-relaxed whitespace-pre-line",
|
|
31000
|
+
}) : field.content.length > 0 && /* @__PURE__ */ jsx("p", {
|
|
31001
|
+
className: "text-xs text-foreground-subtle leading-relaxed whitespace-pre-line break-words",
|
|
30999
31002
|
children: field.content
|
|
31000
31003
|
})]
|
|
31001
31004
|
})
|
|
@@ -61124,28 +61127,61 @@ function FormField$1({ label, description, error, required, children, orientatio
|
|
|
61124
61127
|
}
|
|
61125
61128
|
//#endregion
|
|
61126
61129
|
//#region src/composites/grouped-tile-picker.tsx
|
|
61130
|
+
/**
|
|
61131
|
+
* `GroupedTilePicker` — choose ONE "type of thing" from tiles grouped by who
|
|
61132
|
+
* provides it (an AI profile kind, a notification-target kind…): an uppercase
|
|
61133
|
+
* group label, then a grid of icon + label tiles. The pre-modal of a
|
|
61134
|
+
* create-flow whose form depends on the choice.
|
|
61135
|
+
*
|
|
61136
|
+
* The tile is deliberately not a `Button`: a vertical icon-over-label card in
|
|
61137
|
+
* a grid, which toolbar-button chrome fights. One place owns that look so the
|
|
61138
|
+
* pickers stay identical.
|
|
61139
|
+
*/
|
|
61127
61140
|
function GroupedTilePicker({ groups, onPick, emptyMessage }) {
|
|
61141
|
+
const [openKey, setOpenKey] = useState(null);
|
|
61142
|
+
const openTile = openKey === null ? null : groups.flatMap((group) => group.tiles).find((tile) => tile.key === openKey) ?? null;
|
|
61128
61143
|
return /* @__PURE__ */ jsxs("div", {
|
|
61129
61144
|
className: "space-y-4",
|
|
61130
|
-
children: [
|
|
61131
|
-
|
|
61132
|
-
|
|
61133
|
-
|
|
61134
|
-
|
|
61135
|
-
children:
|
|
61136
|
-
|
|
61137
|
-
|
|
61138
|
-
|
|
61139
|
-
|
|
61140
|
-
|
|
61141
|
-
|
|
61142
|
-
|
|
61143
|
-
|
|
61144
|
-
|
|
61145
|
-
|
|
61146
|
-
|
|
61147
|
-
|
|
61148
|
-
|
|
61145
|
+
children: [
|
|
61146
|
+
groups.length === 0 && /* @__PURE__ */ jsx("p", {
|
|
61147
|
+
className: "text-xs text-foreground-subtle",
|
|
61148
|
+
children: emptyMessage
|
|
61149
|
+
}),
|
|
61150
|
+
groups.map((group) => /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", {
|
|
61151
|
+
className: "mb-1.5 text-[10px] font-semibold uppercase tracking-wider text-foreground-subtle",
|
|
61152
|
+
children: group.label
|
|
61153
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
61154
|
+
className: "grid grid-cols-2 gap-2 sm:grid-cols-3",
|
|
61155
|
+
children: group.tiles.map((tile) => /* @__PURE__ */ jsxs("div", {
|
|
61156
|
+
className: "relative",
|
|
61157
|
+
children: [/* @__PURE__ */ jsxs("button", {
|
|
61158
|
+
type: "button",
|
|
61159
|
+
"data-testid": tile.testId,
|
|
61160
|
+
onClick: () => onPick(tile.key),
|
|
61161
|
+
className: "flex h-full w-full flex-col items-center gap-1.5 rounded-lg border border-border bg-surface px-3 py-3 text-xs transition-colors hover:border-primary/50 hover:bg-surface-hover",
|
|
61162
|
+
children: [tile.icon, /* @__PURE__ */ jsx("span", {
|
|
61163
|
+
className: "text-center font-medium text-foreground",
|
|
61164
|
+
children: tile.label
|
|
61165
|
+
})]
|
|
61166
|
+
}), tile.detail !== void 0 && tile.detailLabel !== void 0 && /* @__PURE__ */ jsx("div", {
|
|
61167
|
+
className: "absolute top-1 right-1",
|
|
61168
|
+
children: /* @__PURE__ */ jsx(IconButton, {
|
|
61169
|
+
type: "button",
|
|
61170
|
+
variant: "ghost",
|
|
61171
|
+
size: "sm",
|
|
61172
|
+
icon: Info,
|
|
61173
|
+
"aria-label": tile.detailLabel,
|
|
61174
|
+
onClick: () => setOpenKey((current) => current === tile.key ? null : tile.key)
|
|
61175
|
+
})
|
|
61176
|
+
})]
|
|
61177
|
+
}, tile.key))
|
|
61178
|
+
})] }, group.id)),
|
|
61179
|
+
openTile?.detail !== void 0 && /* @__PURE__ */ jsx(BottomSheet, {
|
|
61180
|
+
open: true,
|
|
61181
|
+
onClose: () => setOpenKey(null),
|
|
61182
|
+
children: openTile.detail
|
|
61183
|
+
})
|
|
61184
|
+
]
|
|
61149
61185
|
});
|
|
61150
61186
|
}
|
|
61151
61187
|
//#endregion
|