@flytedan/flytebot-design-system 0.9.0 → 0.10.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/index.cjs +1109 -1091
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +37 -7
- package/dist/index.d.ts +37 -7
- package/dist/index.js +1109 -1091
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/styles/components.css +12 -3
package/dist/index.cjs
CHANGED
|
@@ -2946,11 +2946,30 @@ function EntityRow({
|
|
|
2946
2946
|
}
|
|
2947
2947
|
|
|
2948
2948
|
// src/components/data/TransferList.tsx
|
|
2949
|
-
var
|
|
2949
|
+
var React18 = __toESM(require("react"), 1);
|
|
2950
2950
|
var import_react_dom4 = require("react-dom");
|
|
2951
2951
|
|
|
2952
|
-
// src/components/forms/
|
|
2952
|
+
// src/components/forms/field.tsx
|
|
2953
|
+
var React17 = __toESM(require("react"), 1);
|
|
2953
2954
|
var import_jsx_runtime41 = require("react/jsx-runtime");
|
|
2955
|
+
function useFieldId(id) {
|
|
2956
|
+
const generated = React17.useId();
|
|
2957
|
+
return id || generated;
|
|
2958
|
+
}
|
|
2959
|
+
function FieldLabel({ htmlFor, id, required = false, onClick, children }) {
|
|
2960
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { className: "fd-field-label", htmlFor, id, onClick, children: [
|
|
2961
|
+
children,
|
|
2962
|
+
required ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "fd-field-req", "aria-hidden": "true", children: "*" }) : null
|
|
2963
|
+
] });
|
|
2964
|
+
}
|
|
2965
|
+
function useTriggerLabelling(label, id) {
|
|
2966
|
+
const fieldId = useFieldId(id);
|
|
2967
|
+
const labelId = fieldId + "-label";
|
|
2968
|
+
return { fieldId, labelId, ariaLabelledBy: label ? labelId + " " + fieldId : void 0 };
|
|
2969
|
+
}
|
|
2970
|
+
|
|
2971
|
+
// src/components/forms/Input.tsx
|
|
2972
|
+
var import_jsx_runtime42 = require("react/jsx-runtime");
|
|
2954
2973
|
function Input({
|
|
2955
2974
|
label,
|
|
2956
2975
|
help,
|
|
@@ -2969,7 +2988,7 @@ function Input({
|
|
|
2969
2988
|
inputStyle,
|
|
2970
2989
|
...rest
|
|
2971
2990
|
}) {
|
|
2972
|
-
const fieldId = id
|
|
2991
|
+
const fieldId = useFieldId(id);
|
|
2973
2992
|
const box = [
|
|
2974
2993
|
"fd-input",
|
|
2975
2994
|
numeric ? "fd-input-num" : "",
|
|
@@ -2978,27 +2997,24 @@ function Input({
|
|
|
2978
2997
|
size === "lg" ? "fd-input-lg" : "",
|
|
2979
2998
|
className
|
|
2980
2999
|
].filter(Boolean).join(" ");
|
|
2981
|
-
return /* @__PURE__ */ (0,
|
|
2982
|
-
label ? /* @__PURE__ */ (0,
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("input", { id: fieldId, disabled, style: inputStyle, "aria-invalid": error ? "true" : void 0, ...rest }),
|
|
2990
|
-
loading ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "fd-spinner", style: { color: "var(--text-muted)" }, "aria-label": "Loading" }) : null,
|
|
2991
|
-
suffix && !loading ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "fd-input-affix", children: suffix }) : null
|
|
3000
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "fd-field", style, children: [
|
|
3001
|
+
label ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(FieldLabel, { htmlFor: fieldId, required, children: label }) : null,
|
|
3002
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: box, children: [
|
|
3003
|
+
icon ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "fd-input-icon", children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("i", { className: "ph ph-" + icon, "aria-hidden": "true" }) }) : null,
|
|
3004
|
+
prefix ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "fd-input-affix", children: prefix }) : null,
|
|
3005
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("input", { id: fieldId, disabled, style: inputStyle, "aria-invalid": error ? "true" : void 0, ...rest }),
|
|
3006
|
+
loading ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "fd-spinner", style: { color: "var(--text-muted)" }, "aria-label": "Loading" }) : null,
|
|
3007
|
+
suffix && !loading ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "fd-input-affix", children: suffix }) : null
|
|
2992
3008
|
] }),
|
|
2993
|
-
error ? /* @__PURE__ */ (0,
|
|
2994
|
-
/* @__PURE__ */ (0,
|
|
3009
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { className: "fd-field-error", children: [
|
|
3010
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
2995
3011
|
error
|
|
2996
|
-
] }) : help ? /* @__PURE__ */ (0,
|
|
3012
|
+
] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "fd-field-help", children: help }) : null
|
|
2997
3013
|
] });
|
|
2998
3014
|
}
|
|
2999
3015
|
|
|
3000
3016
|
// src/components/forms/SearchField.tsx
|
|
3001
|
-
var
|
|
3017
|
+
var import_jsx_runtime43 = require("react/jsx-runtime");
|
|
3002
3018
|
function SearchField({
|
|
3003
3019
|
value,
|
|
3004
3020
|
onChange,
|
|
@@ -3013,7 +3029,7 @@ function SearchField({
|
|
|
3013
3029
|
...rest
|
|
3014
3030
|
}) {
|
|
3015
3031
|
const clear = onClear || (() => onChange(""));
|
|
3016
|
-
return /* @__PURE__ */ (0,
|
|
3032
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
3017
3033
|
Input,
|
|
3018
3034
|
{
|
|
3019
3035
|
id,
|
|
@@ -3026,14 +3042,14 @@ function SearchField({
|
|
|
3026
3042
|
style,
|
|
3027
3043
|
className,
|
|
3028
3044
|
onChange: (e) => onChange(e.target.value),
|
|
3029
|
-
suffix: value ? /* @__PURE__ */ (0,
|
|
3045
|
+
suffix: value ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
3030
3046
|
"button",
|
|
3031
3047
|
{
|
|
3032
3048
|
type: "button",
|
|
3033
3049
|
"aria-label": "Clear search",
|
|
3034
3050
|
onClick: clear,
|
|
3035
3051
|
style: { all: "unset", cursor: "pointer", color: "var(--text-muted)", display: "grid", placeItems: "center", padding: 2 },
|
|
3036
|
-
children: /* @__PURE__ */ (0,
|
|
3052
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("i", { className: "ph ph-x-circle", style: { fontSize: 15 }, "aria-hidden": "true" })
|
|
3037
3053
|
}
|
|
3038
3054
|
) : void 0,
|
|
3039
3055
|
...rest
|
|
@@ -3042,7 +3058,7 @@ function SearchField({
|
|
|
3042
3058
|
}
|
|
3043
3059
|
|
|
3044
3060
|
// src/components/data/TransferList.tsx
|
|
3045
|
-
var
|
|
3061
|
+
var import_jsx_runtime44 = require("react/jsx-runtime");
|
|
3046
3062
|
var emptyHasMore = {};
|
|
3047
3063
|
var DRAG_THRESHOLD_PX = 5;
|
|
3048
3064
|
function TransferList({
|
|
@@ -3056,12 +3072,12 @@ function TransferList({
|
|
|
3056
3072
|
listHeight = 440,
|
|
3057
3073
|
className = ""
|
|
3058
3074
|
}) {
|
|
3059
|
-
const [drag, setDrag] =
|
|
3060
|
-
const [dragOverSide, setDragOverSide] =
|
|
3061
|
-
const dragRef =
|
|
3062
|
-
const armedRef =
|
|
3063
|
-
const sideRefs =
|
|
3064
|
-
const hitTestSide =
|
|
3075
|
+
const [drag, setDrag] = React18.useState(null);
|
|
3076
|
+
const [dragOverSide, setDragOverSide] = React18.useState(null);
|
|
3077
|
+
const dragRef = React18.useRef(null);
|
|
3078
|
+
const armedRef = React18.useRef(null);
|
|
3079
|
+
const sideRefs = React18.useRef({ left: null, right: null });
|
|
3080
|
+
const hitTestSide = React18.useCallback((x, y) => {
|
|
3065
3081
|
for (const side of ["left", "right"]) {
|
|
3066
3082
|
const el = sideRefs.current[side];
|
|
3067
3083
|
if (!el) continue;
|
|
@@ -3070,7 +3086,7 @@ function TransferList({
|
|
|
3070
3086
|
}
|
|
3071
3087
|
return null;
|
|
3072
3088
|
}, []);
|
|
3073
|
-
const findItem =
|
|
3089
|
+
const findItem = React18.useCallback(
|
|
3074
3090
|
(side, key) => (side === "left" ? left.items : right.items).find((it) => keyOf(it) === key),
|
|
3075
3091
|
[left.items, right.items, keyOf]
|
|
3076
3092
|
);
|
|
@@ -3092,7 +3108,7 @@ function TransferList({
|
|
|
3092
3108
|
height: rect.height
|
|
3093
3109
|
};
|
|
3094
3110
|
};
|
|
3095
|
-
|
|
3111
|
+
React18.useEffect(() => {
|
|
3096
3112
|
const onMovePointer = (e) => {
|
|
3097
3113
|
const armed = armedRef.current;
|
|
3098
3114
|
if (!armed || e.pointerId !== armed.pointerId) return;
|
|
@@ -3145,7 +3161,7 @@ function TransferList({
|
|
|
3145
3161
|
window.removeEventListener("pointercancel", endDrag);
|
|
3146
3162
|
};
|
|
3147
3163
|
}, [hitTestSide, findItem, onMove]);
|
|
3148
|
-
|
|
3164
|
+
React18.useEffect(() => {
|
|
3149
3165
|
if (!drag || typeof document === "undefined") return;
|
|
3150
3166
|
const prev = document.body.style.userSelect;
|
|
3151
3167
|
document.body.style.userSelect = "none";
|
|
@@ -3155,7 +3171,7 @@ function TransferList({
|
|
|
3155
3171
|
}, [drag]);
|
|
3156
3172
|
const renderSide = (side, cfg, opposite) => {
|
|
3157
3173
|
const showOverlay = drag != null && dragOverSide === side;
|
|
3158
|
-
return /* @__PURE__ */ (0,
|
|
3174
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
|
|
3159
3175
|
"div",
|
|
3160
3176
|
{
|
|
3161
3177
|
ref: (el) => {
|
|
@@ -3174,16 +3190,16 @@ function TransferList({
|
|
|
3174
3190
|
position: "relative"
|
|
3175
3191
|
},
|
|
3176
3192
|
children: [
|
|
3177
|
-
cfg.label ? /* @__PURE__ */ (0,
|
|
3193
|
+
cfg.label ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { className: "fd-overline fd-muted", children: [
|
|
3178
3194
|
cfg.label,
|
|
3179
3195
|
cfg.total != null ? " (" + cfg.total.toLocaleString() + ")" : ""
|
|
3180
3196
|
] }) : null,
|
|
3181
|
-
cfg.header ? /* @__PURE__ */ (0,
|
|
3182
|
-
/* @__PURE__ */ (0,
|
|
3183
|
-
/* @__PURE__ */ (0,
|
|
3184
|
-
/* @__PURE__ */ (0,
|
|
3197
|
+
cfg.header ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "fd-tlist-header", children: cfg.header }) : null,
|
|
3198
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
|
|
3199
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(SearchField, { value: cfg.search, onChange: cfg.onSearchChange, placeholder: "Search", "aria-label": (cfg.label || side) + " search", style: { flex: 1 } }),
|
|
3200
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(SortMenu, { fields: cfg.sortFields, sort: cfg.sort, onSort: cfg.onSort, align: side === "left" ? "left" : "right" })
|
|
3185
3201
|
] }),
|
|
3186
|
-
/* @__PURE__ */ (0,
|
|
3202
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
3187
3203
|
VirtualList,
|
|
3188
3204
|
{
|
|
3189
3205
|
items: cfg.items,
|
|
@@ -3197,13 +3213,13 @@ function TransferList({
|
|
|
3197
3213
|
firstItemIndex: cfg.firstItemIndex,
|
|
3198
3214
|
totalCount: cfg.totalCount,
|
|
3199
3215
|
onNeedMore: cfg.onNeedMore,
|
|
3200
|
-
emptyState: /* @__PURE__ */ (0,
|
|
3216
|
+
emptyState: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(EmptyState, { icon: "tray", title: "Nothing here" }),
|
|
3201
3217
|
renderItem: (item) => {
|
|
3202
3218
|
const isBeingDragged = drag != null && drag.from === side && drag.key === keyOf(item);
|
|
3203
3219
|
if (isBeingDragged) {
|
|
3204
|
-
return /* @__PURE__ */ (0,
|
|
3220
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "fd-erow-placeholder", "aria-hidden": "true" });
|
|
3205
3221
|
}
|
|
3206
|
-
return /* @__PURE__ */ (0,
|
|
3222
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
3207
3223
|
EntityRow,
|
|
3208
3224
|
{
|
|
3209
3225
|
...renderRow(item),
|
|
@@ -3220,20 +3236,20 @@ function TransferList({
|
|
|
3220
3236
|
}
|
|
3221
3237
|
}
|
|
3222
3238
|
),
|
|
3223
|
-
cfg.footer ? /* @__PURE__ */ (0,
|
|
3224
|
-
showOverlay ? /* @__PURE__ */ (0,
|
|
3225
|
-
/* @__PURE__ */ (0,
|
|
3226
|
-
/* @__PURE__ */ (0,
|
|
3239
|
+
cfg.footer ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "fd-tlist-footer", children: cfg.footer }) : null,
|
|
3240
|
+
showOverlay ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "fd-tlist-drop-overlay", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { className: "fd-tlist-drop-card", children: [
|
|
3241
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("i", { className: "ph ph-tray-arrow-down", style: { fontSize: 18 }, "aria-hidden": "true" }),
|
|
3242
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: cfg.dropLabel || "Drop here" + (cfg.label ? " \u2014 " + cfg.label : "") })
|
|
3227
3243
|
] }) }) : null
|
|
3228
3244
|
]
|
|
3229
3245
|
}
|
|
3230
3246
|
);
|
|
3231
3247
|
};
|
|
3232
|
-
return /* @__PURE__ */ (0,
|
|
3248
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: ["fd-tlist", className].filter(Boolean).join(" "), style: { display: "flex", gap: 16, alignItems: "flex-start" }, children: [
|
|
3233
3249
|
renderSide("left", left, "right"),
|
|
3234
3250
|
renderSide("right", right, "left"),
|
|
3235
3251
|
drag ? (0, import_react_dom4.createPortal)(
|
|
3236
|
-
/* @__PURE__ */ (0,
|
|
3252
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
3237
3253
|
"div",
|
|
3238
3254
|
{
|
|
3239
3255
|
"aria-hidden": "true",
|
|
@@ -3248,7 +3264,7 @@ function TransferList({
|
|
|
3248
3264
|
pointerEvents: "none",
|
|
3249
3265
|
zIndex: 1e3
|
|
3250
3266
|
},
|
|
3251
|
-
children: /* @__PURE__ */ (0,
|
|
3267
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(EntityRow, { ...renderRow(drag.item), draggable: true, className: "fd-erow-dragging" })
|
|
3252
3268
|
}
|
|
3253
3269
|
),
|
|
3254
3270
|
document.body
|
|
@@ -3257,74 +3273,71 @@ function TransferList({
|
|
|
3257
3273
|
}
|
|
3258
3274
|
|
|
3259
3275
|
// src/components/forms/Checkbox.tsx
|
|
3260
|
-
var
|
|
3261
|
-
var
|
|
3276
|
+
var React19 = __toESM(require("react"), 1);
|
|
3277
|
+
var import_jsx_runtime45 = require("react/jsx-runtime");
|
|
3262
3278
|
function Checkbox({ label, description, card = false, indeterminate = false, className = "", ...rest }) {
|
|
3263
|
-
const ref =
|
|
3264
|
-
|
|
3279
|
+
const ref = React19.useRef(null);
|
|
3280
|
+
React19.useEffect(() => {
|
|
3265
3281
|
if (ref.current) ref.current.indeterminate = indeterminate;
|
|
3266
3282
|
}, [indeterminate]);
|
|
3267
|
-
return /* @__PURE__ */ (0,
|
|
3268
|
-
/* @__PURE__ */ (0,
|
|
3269
|
-
/* @__PURE__ */ (0,
|
|
3270
|
-
/* @__PURE__ */ (0,
|
|
3283
|
+
return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
|
|
3284
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("span", { className: "fd-choice-input", children: [
|
|
3285
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)("input", { ref, type: "checkbox", ...rest }),
|
|
3286
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "fd-choice-box", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("i", { className: indeterminate ? "ph ph-minus" : "ph ph-check" }) })
|
|
3271
3287
|
] }),
|
|
3272
|
-
/* @__PURE__ */ (0,
|
|
3273
|
-
/* @__PURE__ */ (0,
|
|
3274
|
-
description ? /* @__PURE__ */ (0,
|
|
3288
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("span", { className: "fd-choice-text", children: [
|
|
3289
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "fd-choice-title", children: label }),
|
|
3290
|
+
description ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "fd-choice-desc", children: description }) : null
|
|
3275
3291
|
] })
|
|
3276
3292
|
] });
|
|
3277
3293
|
}
|
|
3278
3294
|
|
|
3279
3295
|
// src/components/forms/Radio.tsx
|
|
3280
|
-
var
|
|
3296
|
+
var import_jsx_runtime46 = require("react/jsx-runtime");
|
|
3281
3297
|
function Radio({ label, description, card = false, className = "", ...rest }) {
|
|
3282
|
-
return /* @__PURE__ */ (0,
|
|
3283
|
-
/* @__PURE__ */ (0,
|
|
3284
|
-
/* @__PURE__ */ (0,
|
|
3285
|
-
/* @__PURE__ */ (0,
|
|
3298
|
+
return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
|
|
3299
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("span", { className: "fd-choice-input", children: [
|
|
3300
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)("input", { type: "radio", ...rest }),
|
|
3301
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "fd-choice-box fd-choice-box-round", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "fd-choice-dot" }) })
|
|
3286
3302
|
] }),
|
|
3287
|
-
/* @__PURE__ */ (0,
|
|
3288
|
-
/* @__PURE__ */ (0,
|
|
3289
|
-
description ? /* @__PURE__ */ (0,
|
|
3303
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("span", { className: "fd-choice-text", children: [
|
|
3304
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "fd-choice-title", children: label }),
|
|
3305
|
+
description ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "fd-choice-desc", children: description }) : null
|
|
3290
3306
|
] })
|
|
3291
3307
|
] });
|
|
3292
3308
|
}
|
|
3293
3309
|
|
|
3294
3310
|
// src/components/forms/Switch.tsx
|
|
3295
|
-
var
|
|
3311
|
+
var import_jsx_runtime47 = require("react/jsx-runtime");
|
|
3296
3312
|
function Switch({ label, description, className = "", ...rest }) {
|
|
3297
|
-
return /* @__PURE__ */ (0,
|
|
3298
|
-
/* @__PURE__ */ (0,
|
|
3299
|
-
/* @__PURE__ */ (0,
|
|
3300
|
-
label ? /* @__PURE__ */ (0,
|
|
3301
|
-
/* @__PURE__ */ (0,
|
|
3302
|
-
description ? /* @__PURE__ */ (0,
|
|
3313
|
+
return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("label", { className: ["fd-switch", className].filter(Boolean).join(" "), children: [
|
|
3314
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)("input", { type: "checkbox", role: "switch", ...rest }),
|
|
3315
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "fd-switch-track", children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "fd-switch-thumb" }) }),
|
|
3316
|
+
label ? /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("span", { className: "fd-choice-text", children: [
|
|
3317
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "fd-switch-label", children: label }),
|
|
3318
|
+
description ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "fd-choice-desc", children: description }) : null
|
|
3303
3319
|
] }) : null
|
|
3304
3320
|
] });
|
|
3305
3321
|
}
|
|
3306
3322
|
|
|
3307
3323
|
// src/components/forms/Textarea.tsx
|
|
3308
|
-
var
|
|
3324
|
+
var import_jsx_runtime48 = require("react/jsx-runtime");
|
|
3309
3325
|
function Textarea({ label, help, error, required = false, rows = 4, disabled = false, id, className = "", style, ...rest }) {
|
|
3310
|
-
const fieldId = id
|
|
3326
|
+
const fieldId = useFieldId(id);
|
|
3311
3327
|
const box = ["fd-input", "fd-input-textarea", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : "", className].filter(Boolean).join(" ");
|
|
3312
|
-
return /* @__PURE__ */ (0,
|
|
3313
|
-
label ? /* @__PURE__ */ (0,
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: box, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("textarea", { id: fieldId, rows, disabled, "aria-invalid": error ? "true" : void 0, ...rest }) }),
|
|
3318
|
-
error ? /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("span", { className: "fd-field-error", children: [
|
|
3319
|
-
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
3328
|
+
return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "fd-field", style, children: [
|
|
3329
|
+
label ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(FieldLabel, { htmlFor: fieldId, required, children: label }) : null,
|
|
3330
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: box, children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("textarea", { id: fieldId, rows, disabled, "aria-invalid": error ? "true" : void 0, ...rest }) }),
|
|
3331
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("span", { className: "fd-field-error", children: [
|
|
3332
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
3320
3333
|
error
|
|
3321
|
-
] }) : help ? /* @__PURE__ */ (0,
|
|
3334
|
+
] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "fd-field-help", children: help }) : null
|
|
3322
3335
|
] });
|
|
3323
3336
|
}
|
|
3324
3337
|
|
|
3325
3338
|
// src/components/forms/NumberInput.tsx
|
|
3326
|
-
var
|
|
3327
|
-
var
|
|
3339
|
+
var React20 = __toESM(require("react"), 1);
|
|
3340
|
+
var import_jsx_runtime49 = require("react/jsx-runtime");
|
|
3328
3341
|
function NumberInput({
|
|
3329
3342
|
label,
|
|
3330
3343
|
help,
|
|
@@ -3342,16 +3355,19 @@ function NumberInput({
|
|
|
3342
3355
|
format = true,
|
|
3343
3356
|
className = "",
|
|
3344
3357
|
style,
|
|
3345
|
-
placeholder
|
|
3358
|
+
placeholder,
|
|
3359
|
+
id,
|
|
3360
|
+
"aria-label": ariaLabel
|
|
3346
3361
|
}) {
|
|
3362
|
+
const fieldId = useFieldId(id);
|
|
3347
3363
|
const num = (v) => {
|
|
3348
3364
|
const n = Number(String(v == null ? "" : v).replace(/[^0-9.-]/g, ""));
|
|
3349
3365
|
return isNaN(n) ? null : n;
|
|
3350
3366
|
};
|
|
3351
|
-
const [text, setText] =
|
|
3352
|
-
const [editing, setEditing] =
|
|
3353
|
-
const timer =
|
|
3354
|
-
|
|
3367
|
+
const [text, setText] = React20.useState(value == null || value === "" ? "" : String(value));
|
|
3368
|
+
const [editing, setEditing] = React20.useState(false);
|
|
3369
|
+
const timer = React20.useRef(null);
|
|
3370
|
+
React20.useEffect(() => {
|
|
3355
3371
|
if (!editing) setText(value == null || value === "" ? "" : String(value));
|
|
3356
3372
|
}, [value, editing]);
|
|
3357
3373
|
const clamp = (n) => Math.min(max, Math.max(min, n));
|
|
@@ -3375,7 +3391,7 @@ function NumberInput({
|
|
|
3375
3391
|
const release = () => {
|
|
3376
3392
|
if (timer.current) clearTimeout(timer.current);
|
|
3377
3393
|
};
|
|
3378
|
-
|
|
3394
|
+
React20.useEffect(() => () => {
|
|
3379
3395
|
if (timer.current) clearTimeout(timer.current);
|
|
3380
3396
|
}, []);
|
|
3381
3397
|
const shown = editing ? text : (() => {
|
|
@@ -3383,16 +3399,17 @@ function NumberInput({
|
|
|
3383
3399
|
return n == null ? "" : format ? n.toLocaleString() : String(n);
|
|
3384
3400
|
})();
|
|
3385
3401
|
const box = ["fd-input", "fd-input-num", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : ""].filter(Boolean).join(" ");
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
3402
|
+
const fieldName = label || ariaLabel;
|
|
3403
|
+
const stepperName = (verb) => fieldName ? verb + " " + fieldName : verb;
|
|
3404
|
+
return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: ["fd-field", className].filter(Boolean).join(" "), style, children: [
|
|
3405
|
+
label ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(FieldLabel, { htmlFor: fieldId, required, children: label }) : null,
|
|
3406
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: box, style: { gap: 8 }, children: [
|
|
3407
|
+
prefix ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "fd-input-affix", children: prefix }) : null,
|
|
3408
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
|
|
3394
3409
|
"input",
|
|
3395
3410
|
{
|
|
3411
|
+
id: fieldId,
|
|
3412
|
+
"aria-label": ariaLabel,
|
|
3396
3413
|
inputMode: "numeric",
|
|
3397
3414
|
disabled,
|
|
3398
3415
|
placeholder,
|
|
@@ -3423,51 +3440,51 @@ function NumberInput({
|
|
|
3423
3440
|
}
|
|
3424
3441
|
}
|
|
3425
3442
|
),
|
|
3426
|
-
suffix ? /* @__PURE__ */ (0,
|
|
3427
|
-
/* @__PURE__ */ (0,
|
|
3428
|
-
/* @__PURE__ */ (0,
|
|
3443
|
+
suffix ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "fd-input-affix", children: suffix }) : null,
|
|
3444
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("span", { className: "fd-row", style: { gap: 4, flex: "none" }, children: [
|
|
3445
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
|
|
3429
3446
|
"button",
|
|
3430
3447
|
{
|
|
3431
3448
|
type: "button",
|
|
3432
3449
|
className: "fd-stepbtn",
|
|
3433
|
-
"aria-label": "Decrease",
|
|
3450
|
+
"aria-label": stepperName("Decrease"),
|
|
3434
3451
|
disabled: disabled || (num(text) ?? 0) <= min,
|
|
3435
3452
|
onPointerDown: () => hold(-1),
|
|
3436
3453
|
onPointerUp: release,
|
|
3437
3454
|
onPointerLeave: release,
|
|
3438
|
-
children: /* @__PURE__ */ (0,
|
|
3455
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("i", { className: "ph ph-minus" })
|
|
3439
3456
|
}
|
|
3440
3457
|
),
|
|
3441
|
-
/* @__PURE__ */ (0,
|
|
3458
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
|
|
3442
3459
|
"button",
|
|
3443
3460
|
{
|
|
3444
3461
|
type: "button",
|
|
3445
3462
|
className: "fd-stepbtn",
|
|
3446
|
-
"aria-label": "Increase",
|
|
3463
|
+
"aria-label": stepperName("Increase"),
|
|
3447
3464
|
disabled: disabled || (num(text) ?? 0) >= max,
|
|
3448
3465
|
onPointerDown: () => hold(1),
|
|
3449
3466
|
onPointerUp: release,
|
|
3450
3467
|
onPointerLeave: release,
|
|
3451
|
-
children: /* @__PURE__ */ (0,
|
|
3468
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("i", { className: "ph ph-plus" })
|
|
3452
3469
|
}
|
|
3453
3470
|
)
|
|
3454
3471
|
] })
|
|
3455
3472
|
] }),
|
|
3456
|
-
error ? /* @__PURE__ */ (0,
|
|
3457
|
-
/* @__PURE__ */ (0,
|
|
3473
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("span", { className: "fd-field-error", children: [
|
|
3474
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
3458
3475
|
error
|
|
3459
|
-
] }) : help ? /* @__PURE__ */ (0,
|
|
3476
|
+
] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "fd-field-help", children: help }) : null
|
|
3460
3477
|
] });
|
|
3461
3478
|
}
|
|
3462
3479
|
|
|
3463
3480
|
// src/components/forms/Select.tsx
|
|
3464
|
-
var
|
|
3481
|
+
var React21 = __toESM(require("react"), 1);
|
|
3465
3482
|
var import_react_dom5 = require("react-dom");
|
|
3466
|
-
var
|
|
3483
|
+
var import_jsx_runtime50 = require("react/jsx-runtime");
|
|
3467
3484
|
var norm = (o) => typeof o === "string" ? { value: o, label: o } : o;
|
|
3468
3485
|
function usePopPos(open, ref, estH, estW) {
|
|
3469
|
-
const [pos, setPos] =
|
|
3470
|
-
|
|
3486
|
+
const [pos, setPos] = React21.useState(null);
|
|
3487
|
+
React21.useLayoutEffect(() => {
|
|
3471
3488
|
if (!open || !ref.current) {
|
|
3472
3489
|
setPos(null);
|
|
3473
3490
|
return;
|
|
@@ -3524,21 +3541,21 @@ function Select({
|
|
|
3524
3541
|
summary,
|
|
3525
3542
|
id,
|
|
3526
3543
|
className = "",
|
|
3527
|
-
style
|
|
3528
|
-
...rest
|
|
3544
|
+
style
|
|
3529
3545
|
}) {
|
|
3530
3546
|
const opts = options.map(norm);
|
|
3531
3547
|
const vals = multiple ? Array.isArray(value) ? value : value ? [value] : [] : [];
|
|
3532
3548
|
const isOn = (v) => multiple ? vals.includes(v) : v === value;
|
|
3533
3549
|
const hasSearch = searchable === void 0 ? opts.length > 8 : searchable;
|
|
3534
|
-
const
|
|
3535
|
-
const [
|
|
3536
|
-
const [
|
|
3537
|
-
const
|
|
3538
|
-
const
|
|
3539
|
-
const
|
|
3540
|
-
const
|
|
3541
|
-
const
|
|
3550
|
+
const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id);
|
|
3551
|
+
const [open, setOpen] = React21.useState(false);
|
|
3552
|
+
const [q, setQ] = React21.useState("");
|
|
3553
|
+
const [active, setActive] = React21.useState(-1);
|
|
3554
|
+
const rootRef = React21.useRef(null);
|
|
3555
|
+
const boxRef = React21.useRef(null);
|
|
3556
|
+
const popRef = React21.useRef(null);
|
|
3557
|
+
const listRef = React21.useRef(null);
|
|
3558
|
+
const typeBuf = React21.useRef({ s: "", t: 0 });
|
|
3542
3559
|
const selected = multiple ? null : opts.find((o) => o.value === value);
|
|
3543
3560
|
const chosen = multiple ? opts.filter((o) => vals.includes(o.value)) : [];
|
|
3544
3561
|
const pos = usePopPos(open, boxRef, hasSearch ? 390 : 340, 260);
|
|
@@ -3564,7 +3581,7 @@ function Select({
|
|
|
3564
3581
|
}
|
|
3565
3582
|
setOpen(!open);
|
|
3566
3583
|
};
|
|
3567
|
-
|
|
3584
|
+
React21.useEffect(() => {
|
|
3568
3585
|
if (!open) return;
|
|
3569
3586
|
const away = (e) => {
|
|
3570
3587
|
if (rootRef.current && rootRef.current.contains(e.target)) return;
|
|
@@ -3574,7 +3591,7 @@ function Select({
|
|
|
3574
3591
|
document.addEventListener("pointerdown", away);
|
|
3575
3592
|
return () => document.removeEventListener("pointerdown", away);
|
|
3576
3593
|
}, [open]);
|
|
3577
|
-
|
|
3594
|
+
React21.useEffect(() => {
|
|
3578
3595
|
if (!open || active < 0 || !listRef.current) return;
|
|
3579
3596
|
const el = listRef.current.querySelector('[data-i="' + active + '"]');
|
|
3580
3597
|
if (el) {
|
|
@@ -3626,15 +3643,11 @@ function Select({
|
|
|
3626
3643
|
if (!last || last.g !== g) groups.push({ g, items: [{ o, i }] });
|
|
3627
3644
|
else last.items.push({ o, i });
|
|
3628
3645
|
});
|
|
3629
|
-
const fieldId = id || (rest.name ? "fd-" + rest.name : void 0);
|
|
3630
3646
|
const box = ["fd-input", "fd-select", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : ""].filter(Boolean).join(" ");
|
|
3631
|
-
return /* @__PURE__ */ (0,
|
|
3632
|
-
label ? /* @__PURE__ */ (0,
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
] }) : null,
|
|
3636
|
-
/* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: box, style: { cursor: disabled ? "not-allowed" : "pointer" }, ref: boxRef, children: [
|
|
3637
|
-
/* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(
|
|
3647
|
+
return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: ["fd-field", "fd-popfield", open ? "is-open" : "", className].filter(Boolean).join(" "), style, ref: rootRef, children: [
|
|
3648
|
+
label ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(FieldLabel, { id: labelId, required, onClick: toggle, children: label }) : null,
|
|
3649
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: box, style: { cursor: disabled ? "not-allowed" : "pointer" }, ref: boxRef, children: [
|
|
3650
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(
|
|
3638
3651
|
"button",
|
|
3639
3652
|
{
|
|
3640
3653
|
type: "button",
|
|
@@ -3645,15 +3658,16 @@ function Select({
|
|
|
3645
3658
|
role: "combobox",
|
|
3646
3659
|
"aria-expanded": open,
|
|
3647
3660
|
"aria-haspopup": "listbox",
|
|
3661
|
+
"aria-labelledby": ariaLabelledBy,
|
|
3648
3662
|
style: { all: "unset", flex: 1, minWidth: 0, display: "flex", alignItems: "center", gap: 8, cursor: "inherit", overflow: "hidden" },
|
|
3649
3663
|
children: [
|
|
3650
|
-
selected && selected.icon ? /* @__PURE__ */ (0,
|
|
3651
|
-
/* @__PURE__ */ (0,
|
|
3652
|
-
multiple && chosen.length > 1 ? /* @__PURE__ */ (0,
|
|
3664
|
+
selected && selected.icon ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("i", { className: "ph ph-" + selected.icon, style: { flex: "none", color: "var(--text-2)" } }) : null,
|
|
3665
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { style: { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", color: (multiple ? chosen.length : selected) ? "var(--text)" : "var(--text-muted)" }, children: boxText }),
|
|
3666
|
+
multiple && chosen.length > 1 ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-mono", style: { flex: "none", fontSize: 11, fontWeight: 700, padding: "1px 6px", borderRadius: 99, background: "var(--brand)", color: "#fff" }, children: chosen.length }) : null
|
|
3653
3667
|
]
|
|
3654
3668
|
}
|
|
3655
3669
|
),
|
|
3656
|
-
clearable && (multiple ? chosen.length > 0 : selected) && !loading ? /* @__PURE__ */ (0,
|
|
3670
|
+
clearable && (multiple ? chosen.length > 0 : selected) && !loading ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3657
3671
|
"button",
|
|
3658
3672
|
{
|
|
3659
3673
|
type: "button",
|
|
@@ -3663,22 +3677,22 @@ function Select({
|
|
|
3663
3677
|
fire(multiple ? [] : "");
|
|
3664
3678
|
},
|
|
3665
3679
|
style: { all: "unset", cursor: "pointer", color: "var(--text-muted)", display: "grid", placeItems: "center", padding: 2 },
|
|
3666
|
-
children: /* @__PURE__ */ (0,
|
|
3680
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("i", { className: "ph ph-x-circle", style: { fontSize: 15 } })
|
|
3667
3681
|
}
|
|
3668
3682
|
) : null,
|
|
3669
|
-
loading ? /* @__PURE__ */ (0,
|
|
3683
|
+
loading ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-spinner", style: { color: "var(--text-muted)" }, "aria-label": "Loading options" }) : /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-select-caret", onClick: toggle, children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("i", { className: "ph ph-caret-down", "aria-hidden": "true" }) })
|
|
3670
3684
|
] }),
|
|
3671
3685
|
open && pos ? (0, import_react_dom5.createPortal)(
|
|
3672
|
-
/* @__PURE__ */ (0,
|
|
3686
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(
|
|
3673
3687
|
"div",
|
|
3674
3688
|
{
|
|
3675
3689
|
className: "fd-pop" + (pos.up ? " is-up" : ""),
|
|
3676
3690
|
ref: popRef,
|
|
3677
3691
|
style: popStyle(pos, { minWidth: Math.max(pos.width, 260), maxWidth: 380, zIndex: 130, overflowY: "hidden" }),
|
|
3678
3692
|
children: [
|
|
3679
|
-
hasSearch ? /* @__PURE__ */ (0,
|
|
3680
|
-
/* @__PURE__ */ (0,
|
|
3681
|
-
/* @__PURE__ */ (0,
|
|
3693
|
+
hasSearch ? /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "fd-pop-search", children: [
|
|
3694
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("i", { className: "ph ph-magnifying-glass", style: { color: "var(--text-muted)", fontSize: 14 } }),
|
|
3695
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3682
3696
|
"input",
|
|
3683
3697
|
{
|
|
3684
3698
|
autoFocus: true,
|
|
@@ -3691,15 +3705,15 @@ function Select({
|
|
|
3691
3705
|
}
|
|
3692
3706
|
}
|
|
3693
3707
|
),
|
|
3694
|
-
q ? /* @__PURE__ */ (0,
|
|
3708
|
+
q ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-body-sm fd-muted", children: visible.length }) : null
|
|
3695
3709
|
] }) : null,
|
|
3696
|
-
/* @__PURE__ */ (0,
|
|
3710
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "fd-pop-list", role: "listbox", "aria-multiselectable": multiple || void 0, ref: listRef, style: { maxHeight: Math.max(120, pos.maxH - (hasSearch ? 64 : 12) - (multiple ? 42 : 0)) }, children: visible.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "fd-pop-empty", children: [
|
|
3697
3711
|
'Nothing matches "',
|
|
3698
3712
|
q,
|
|
3699
3713
|
'".'
|
|
3700
|
-
] }) : groups.map((grp) => /* @__PURE__ */ (0,
|
|
3701
|
-
grp.g ? /* @__PURE__ */ (0,
|
|
3702
|
-
grp.items.map(({ o, i }) => /* @__PURE__ */ (0,
|
|
3714
|
+
] }) : groups.map((grp) => /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(React21.Fragment, { children: [
|
|
3715
|
+
grp.g ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "fd-pop-group", children: grp.g }) : null,
|
|
3716
|
+
grp.items.map(({ o, i }) => /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(
|
|
3703
3717
|
"button",
|
|
3704
3718
|
{
|
|
3705
3719
|
type: "button",
|
|
@@ -3711,21 +3725,21 @@ function Select({
|
|
|
3711
3725
|
onMouseEnter: () => setActive(i),
|
|
3712
3726
|
onClick: () => pick(o),
|
|
3713
3727
|
children: [
|
|
3714
|
-
multiple ? /* @__PURE__ */ (0,
|
|
3715
|
-
o.icon ? /* @__PURE__ */ (0,
|
|
3716
|
-
/* @__PURE__ */ (0,
|
|
3717
|
-
/* @__PURE__ */ (0,
|
|
3718
|
-
o.description ? /* @__PURE__ */ (0,
|
|
3728
|
+
multiple ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { "aria-hidden": "true", style: { flex: "none", display: "grid", placeItems: "center", width: 16, height: 16, borderRadius: 4, border: "1.5px solid " + (isOn(o.value) ? "var(--brand)" : "var(--border-strong, var(--border))"), background: isOn(o.value) ? "var(--brand)" : "var(--surface)", color: "#fff" }, children: isOn(o.value) ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("i", { className: "ph ph-check", style: { fontSize: 11 } }) : null }) : null,
|
|
3729
|
+
o.icon ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-opt-icon", children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("i", { className: "ph ph-" + o.icon }) }) : null,
|
|
3730
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("span", { style: { flex: 1, minWidth: 0 }, children: [
|
|
3731
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-opt-label", children: o.label }),
|
|
3732
|
+
o.description ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-opt-desc", children: o.description }) : null
|
|
3719
3733
|
] }),
|
|
3720
|
-
o.meta ? /* @__PURE__ */ (0,
|
|
3721
|
-
multiple ? null : /* @__PURE__ */ (0,
|
|
3734
|
+
o.meta ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-opt-meta", children: o.meta }) : null,
|
|
3735
|
+
multiple ? null : /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-opt-check", children: o.value === value ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("i", { className: "ph ph-check" }) : null })
|
|
3722
3736
|
]
|
|
3723
3737
|
},
|
|
3724
3738
|
String(o.value)
|
|
3725
3739
|
))
|
|
3726
3740
|
] }, grp.g || "_")) }),
|
|
3727
|
-
multiple ? /* @__PURE__ */ (0,
|
|
3728
|
-
/* @__PURE__ */ (0,
|
|
3741
|
+
multiple ? /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "8px 12px", borderTop: "1px solid var(--border)" }, children: [
|
|
3742
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3729
3743
|
"button",
|
|
3730
3744
|
{
|
|
3731
3745
|
type: "button",
|
|
@@ -3734,13 +3748,13 @@ function Select({
|
|
|
3734
3748
|
children: "Select all"
|
|
3735
3749
|
}
|
|
3736
3750
|
),
|
|
3737
|
-
/* @__PURE__ */ (0,
|
|
3738
|
-
/* @__PURE__ */ (0,
|
|
3751
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { style: { flex: 1 } }),
|
|
3752
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
|
|
3739
3753
|
vals.length,
|
|
3740
3754
|
" of ",
|
|
3741
3755
|
opts.length
|
|
3742
3756
|
] }),
|
|
3743
|
-
/* @__PURE__ */ (0,
|
|
3757
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3744
3758
|
"button",
|
|
3745
3759
|
{
|
|
3746
3760
|
type: "button",
|
|
@@ -3756,17 +3770,17 @@ function Select({
|
|
|
3756
3770
|
),
|
|
3757
3771
|
document.body
|
|
3758
3772
|
) : null,
|
|
3759
|
-
error ? /* @__PURE__ */ (0,
|
|
3760
|
-
/* @__PURE__ */ (0,
|
|
3773
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("span", { className: "fd-field-error", children: [
|
|
3774
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
3761
3775
|
error
|
|
3762
|
-
] }) : help ? /* @__PURE__ */ (0,
|
|
3776
|
+
] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-field-help", children: help }) : null
|
|
3763
3777
|
] });
|
|
3764
3778
|
}
|
|
3765
3779
|
|
|
3766
3780
|
// src/components/forms/DatePicker.tsx
|
|
3767
|
-
var
|
|
3781
|
+
var React22 = __toESM(require("react"), 1);
|
|
3768
3782
|
var import_react_dom6 = require("react-dom");
|
|
3769
|
-
var
|
|
3783
|
+
var import_jsx_runtime51 = require("react/jsx-runtime");
|
|
3770
3784
|
var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
|
3771
3785
|
var DOW = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
|
|
3772
3786
|
var iso = (d) => d.getFullYear() + "-" + String(d.getMonth() + 1).padStart(2, "0") + "-" + String(d.getDate()).padStart(2, "0");
|
|
@@ -3780,8 +3794,8 @@ var fmt = (s) => {
|
|
|
3780
3794
|
return d ? MONTHS[d.getMonth()].slice(0, 3) + " " + d.getDate() + ", " + d.getFullYear() : "";
|
|
3781
3795
|
};
|
|
3782
3796
|
function usePopPos2(open, ref, estH, estW) {
|
|
3783
|
-
const [pos, setPos] =
|
|
3784
|
-
|
|
3797
|
+
const [pos, setPos] = React22.useState(null);
|
|
3798
|
+
React22.useLayoutEffect(() => {
|
|
3785
3799
|
if (!open || !ref.current) {
|
|
3786
3800
|
setPos(null);
|
|
3787
3801
|
return;
|
|
@@ -3825,10 +3839,10 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3825
3839
|
const today = /* @__PURE__ */ new Date();
|
|
3826
3840
|
const sel = range ? value || {} : { start: value, end: value };
|
|
3827
3841
|
const anchor = parse(sel.start) || parse(initialMonth) || today;
|
|
3828
|
-
const [vy, setVy] =
|
|
3829
|
-
const [vm, setVm] =
|
|
3830
|
-
const [mode2, setMode] =
|
|
3831
|
-
const [hover, setHover] =
|
|
3842
|
+
const [vy, setVy] = React22.useState(anchor.getFullYear());
|
|
3843
|
+
const [vm, setVm] = React22.useState(anchor.getMonth());
|
|
3844
|
+
const [mode2, setMode] = React22.useState("days");
|
|
3845
|
+
const [hover, setHover] = React22.useState(null);
|
|
3832
3846
|
const s = parse(sel.start), e = parse(sel.end);
|
|
3833
3847
|
const hoverEnd = range && s && !e && hover ? parse(hover) : null;
|
|
3834
3848
|
const inRange = (d) => {
|
|
@@ -3865,9 +3879,9 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3865
3879
|
const startPad = new Date(y, m, 1).getDay();
|
|
3866
3880
|
const cells = [];
|
|
3867
3881
|
for (let i = 0; i < 42; i++) cells.push(new Date(y, m, i - startPad + 1));
|
|
3868
|
-
return /* @__PURE__ */ (0,
|
|
3869
|
-
DOW.map((d) => /* @__PURE__ */ (0,
|
|
3870
|
-
cells.map((d, i) => /* @__PURE__ */ (0,
|
|
3882
|
+
return /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: "fd-cal-grid", style: { width: months > 1 ? 252 : "auto", flex: "none" }, onMouseLeave: () => setHover(null), children: [
|
|
3883
|
+
DOW.map((d) => /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "fd-cal-dow", children: d }, d)),
|
|
3884
|
+
cells.map((d, i) => /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
3871
3885
|
"button",
|
|
3872
3886
|
{
|
|
3873
3887
|
type: "button",
|
|
@@ -3881,20 +3895,20 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3881
3895
|
] });
|
|
3882
3896
|
};
|
|
3883
3897
|
const nextY = vm === 11 ? vy + 1 : vy, nextM = (vm + 1) % 12;
|
|
3884
|
-
return /* @__PURE__ */ (0,
|
|
3885
|
-
/* @__PURE__ */ (0,
|
|
3886
|
-
/* @__PURE__ */ (0,
|
|
3887
|
-
/* @__PURE__ */ (0,
|
|
3898
|
+
return /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: "fd-cal", style: { width: months > 1 && mode2 === "days" ? "auto" : void 0 }, children: [
|
|
3899
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: "fd-cal-head", children: [
|
|
3900
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)("button", { type: "button", className: "fd-btn-icon", "aria-label": "Previous", onClick: () => mode2 === "years" ? setVy(vy - 12) : mode2 === "months" ? setVy(vy - 1) : nav(-1), children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("i", { className: "ph ph-caret-left" }) }),
|
|
3901
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("button", { type: "button", className: "fd-cal-title", onClick: () => setMode(mode2 === "days" ? "months" : mode2 === "months" ? "years" : "days"), children: [
|
|
3888
3902
|
mode2 === "days" ? MONTHS[vm] + " " + vy : mode2 === "months" ? vy : vy - 5 + " \u2013 " + (vy + 6),
|
|
3889
|
-
/* @__PURE__ */ (0,
|
|
3903
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)("i", { className: "ph ph-caret-down", style: { fontSize: 10, marginLeft: 6, color: "var(--text-muted)" } })
|
|
3890
3904
|
] }),
|
|
3891
|
-
months > 1 && mode2 === "days" ? /* @__PURE__ */ (0,
|
|
3892
|
-
/* @__PURE__ */ (0,
|
|
3905
|
+
months > 1 && mode2 === "days" ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "fd-cal-title", style: { cursor: "default", background: "none" }, children: MONTHS[nextM] + " " + nextY }) : null,
|
|
3906
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)("button", { type: "button", className: "fd-btn-icon", "aria-label": "Next", onClick: () => mode2 === "years" ? setVy(vy + 12) : mode2 === "months" ? setVy(vy + 1) : nav(1), children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("i", { className: "ph ph-caret-right" }) })
|
|
3893
3907
|
] }),
|
|
3894
|
-
mode2 === "days" ? /* @__PURE__ */ (0,
|
|
3908
|
+
mode2 === "days" ? /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { style: { display: "flex", gap: 18 }, children: [
|
|
3895
3909
|
monthGrid(vy, vm),
|
|
3896
3910
|
months > 1 ? monthGrid(nextY, nextM) : null
|
|
3897
|
-
] }) : mode2 === "months" ? /* @__PURE__ */ (0,
|
|
3911
|
+
] }) : mode2 === "months" ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { className: "fd-cal-grid-months", children: MONTHS.map((m, i) => /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
3898
3912
|
"button",
|
|
3899
3913
|
{
|
|
3900
3914
|
type: "button",
|
|
@@ -3906,7 +3920,7 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3906
3920
|
children: m.slice(0, 3)
|
|
3907
3921
|
},
|
|
3908
3922
|
m
|
|
3909
|
-
)) }) : /* @__PURE__ */ (0,
|
|
3923
|
+
)) }) : /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { className: "fd-cal-grid-months", children: Array.from({ length: 12 }, (_, i) => vy - 5 + i).map((y) => /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
3910
3924
|
"button",
|
|
3911
3925
|
{
|
|
3912
3926
|
type: "button",
|
|
@@ -3919,8 +3933,8 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3919
3933
|
},
|
|
3920
3934
|
y
|
|
3921
3935
|
)) }),
|
|
3922
|
-
/* @__PURE__ */ (0,
|
|
3923
|
-
/* @__PURE__ */ (0,
|
|
3936
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: "fd-cal-foot", children: [
|
|
3937
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
3924
3938
|
"button",
|
|
3925
3939
|
{
|
|
3926
3940
|
type: "button",
|
|
@@ -3934,21 +3948,22 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
|
|
|
3934
3948
|
children: "Today"
|
|
3935
3949
|
}
|
|
3936
3950
|
),
|
|
3937
|
-
/* @__PURE__ */ (0,
|
|
3938
|
-
range && sel.start ? /* @__PURE__ */ (0,
|
|
3951
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { style: { flex: 1 } }),
|
|
3952
|
+
range && sel.start ? /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
|
|
3939
3953
|
fmt(sel.start),
|
|
3940
3954
|
sel.end ? " \u2192 " + fmt(sel.end) : " \u2192 pick an end"
|
|
3941
3955
|
] }) : null
|
|
3942
3956
|
] })
|
|
3943
3957
|
] });
|
|
3944
3958
|
}
|
|
3945
|
-
function DatePicker({ label, help, error, required = false, disabled = false, range = false, value, onChange, placeholder, className = "", style, ...rest }) {
|
|
3946
|
-
const
|
|
3947
|
-
const
|
|
3948
|
-
const
|
|
3949
|
-
const
|
|
3959
|
+
function DatePicker({ label, help, error, required = false, disabled = false, range = false, value, onChange, placeholder, id, className = "", style, ...rest }) {
|
|
3960
|
+
const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id);
|
|
3961
|
+
const [open, setOpen] = React22.useState(false);
|
|
3962
|
+
const rootRef = React22.useRef(null);
|
|
3963
|
+
const boxRef = React22.useRef(null);
|
|
3964
|
+
const popRef = React22.useRef(null);
|
|
3950
3965
|
const pos = usePopPos2(open, boxRef, 430, range ? 600 : 316);
|
|
3951
|
-
|
|
3966
|
+
React22.useEffect(() => {
|
|
3952
3967
|
if (!open) return;
|
|
3953
3968
|
const away = (e) => {
|
|
3954
3969
|
if (rootRef.current && rootRef.current.contains(e.target)) return;
|
|
@@ -3969,17 +3984,16 @@ function DatePicker({ label, help, error, required = false, disabled = false, ra
|
|
|
3969
3984
|
const toggle = () => {
|
|
3970
3985
|
if (!disabled) setOpen(!open);
|
|
3971
3986
|
};
|
|
3972
|
-
return /* @__PURE__ */ (0,
|
|
3973
|
-
label ? /* @__PURE__ */ (0,
|
|
3974
|
-
|
|
3975
|
-
|
|
3976
|
-
|
|
3977
|
-
/* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: ["fd-input", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : ""].filter(Boolean).join(" "), style: { cursor: disabled ? "not-allowed" : "pointer" }, onClick: toggle, ref: boxRef, children: [
|
|
3978
|
-
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-input-icon", children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }) }),
|
|
3979
|
-
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3987
|
+
return /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: ["fd-field", "fd-popfield", open ? "is-open" : "", className].filter(Boolean).join(" "), style, ref: rootRef, children: [
|
|
3988
|
+
label ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(FieldLabel, { id: labelId, required, onClick: toggle, children: label }) : null,
|
|
3989
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: ["fd-input", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : ""].filter(Boolean).join(" "), style: { cursor: disabled ? "not-allowed" : "pointer" }, onClick: toggle, ref: boxRef, children: [
|
|
3990
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "fd-input-icon", children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }) }),
|
|
3991
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
3980
3992
|
"button",
|
|
3981
3993
|
{
|
|
3982
3994
|
type: "button",
|
|
3995
|
+
id: fieldId,
|
|
3996
|
+
"aria-labelledby": ariaLabelledBy,
|
|
3983
3997
|
disabled,
|
|
3984
3998
|
onKeyDown: (e) => {
|
|
3985
3999
|
if (e.key === "Enter" || e.key === " ") {
|
|
@@ -3992,10 +4006,10 @@ function DatePicker({ label, help, error, required = false, disabled = false, ra
|
|
|
3992
4006
|
children: display || placeholder || (range ? "Pick a date range" : "Pick a date")
|
|
3993
4007
|
}
|
|
3994
4008
|
),
|
|
3995
|
-
/* @__PURE__ */ (0,
|
|
4009
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "fd-select-caret", children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("i", { className: "ph ph-caret-down", "aria-hidden": "true" }) })
|
|
3996
4010
|
] }),
|
|
3997
4011
|
open && pos ? (0, import_react_dom6.createPortal)(
|
|
3998
|
-
/* @__PURE__ */ (0,
|
|
4012
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { className: "fd-pop" + (pos.up ? " is-up" : ""), ref: popRef, style: popStyle2(pos, { width: "max-content", minWidth: 0, zIndex: 130 }), children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
3999
4013
|
Calendar,
|
|
4000
4014
|
{
|
|
4001
4015
|
range,
|
|
@@ -4009,21 +4023,21 @@ function DatePicker({ label, help, error, required = false, disabled = false, ra
|
|
|
4009
4023
|
) }),
|
|
4010
4024
|
document.body
|
|
4011
4025
|
) : null,
|
|
4012
|
-
error ? /* @__PURE__ */ (0,
|
|
4013
|
-
/* @__PURE__ */ (0,
|
|
4026
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("span", { className: "fd-field-error", children: [
|
|
4027
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
4014
4028
|
error
|
|
4015
|
-
] }) : help ? /* @__PURE__ */ (0,
|
|
4029
|
+
] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "fd-field-help", children: help }) : null
|
|
4016
4030
|
] });
|
|
4017
4031
|
}
|
|
4018
4032
|
|
|
4019
4033
|
// src/components/forms/TimePicker.tsx
|
|
4020
|
-
var
|
|
4034
|
+
var React23 = __toESM(require("react"), 1);
|
|
4021
4035
|
var import_react_dom7 = require("react-dom");
|
|
4022
|
-
var
|
|
4036
|
+
var import_jsx_runtime52 = require("react/jsx-runtime");
|
|
4023
4037
|
var pad = (n) => String(n).padStart(2, "0");
|
|
4024
4038
|
function usePopPos3(open, ref, estH, estW) {
|
|
4025
|
-
const [pos, setPos] =
|
|
4026
|
-
|
|
4039
|
+
const [pos, setPos] = React23.useState(null);
|
|
4040
|
+
React23.useLayoutEffect(() => {
|
|
4027
4041
|
if (!open || !ref.current) {
|
|
4028
4042
|
setPos(null);
|
|
4029
4043
|
return;
|
|
@@ -4069,9 +4083,9 @@ function ClockFace({ value = "09:00", onChange }) {
|
|
|
4069
4083
|
if (isNaN(m)) m = 0;
|
|
4070
4084
|
const pm = h24 >= 12;
|
|
4071
4085
|
const h12 = h24 % 12 === 0 ? 12 : h24 % 12;
|
|
4072
|
-
const [mode2, setMode] =
|
|
4073
|
-
const faceRef =
|
|
4074
|
-
const dragging =
|
|
4086
|
+
const [mode2, setMode] = React23.useState("h");
|
|
4087
|
+
const faceRef = React23.useRef(null);
|
|
4088
|
+
const dragging = React23.useRef(false);
|
|
4075
4089
|
const set = (h, mm, isPm) => onChange((isPm ? h % 12 + 12 : h % 12) + ":" + pad(mm));
|
|
4076
4090
|
const R = 108, NR = 80;
|
|
4077
4091
|
const nums = mode2 === "h" ? Array.from({ length: 12 }, (_, i) => i + 1) : Array.from({ length: 12 }, (_, i) => i * 5);
|
|
@@ -4106,12 +4120,12 @@ function ClockFace({ value = "09:00", onChange }) {
|
|
|
4106
4120
|
};
|
|
4107
4121
|
const handAngle = mode2 === "h" ? h12 % 12 * 30 : m * 6;
|
|
4108
4122
|
const minuteOff = mode2 === "m" && m % 5 !== 0;
|
|
4109
|
-
return /* @__PURE__ */ (0,
|
|
4110
|
-
/* @__PURE__ */ (0,
|
|
4111
|
-
/* @__PURE__ */ (0,
|
|
4112
|
-
/* @__PURE__ */ (0,
|
|
4113
|
-
/* @__PURE__ */ (0,
|
|
4114
|
-
/* @__PURE__ */ (0,
|
|
4123
|
+
return /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { style: { padding: "4px 14px 14px" }, children: [
|
|
4124
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "fd-clock-digits", children: [
|
|
4125
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)("button", { type: "button", className: "fd-clock-digit" + (mode2 === "h" ? " is-active" : ""), onClick: () => setMode("h"), children: pad(h12) }),
|
|
4126
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { style: { fontSize: 24, fontWeight: 700, color: "var(--text-muted)" }, children: ":" }),
|
|
4127
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)("button", { type: "button", className: "fd-clock-digit" + (mode2 === "m" ? " is-active" : ""), onClick: () => setMode("m"), children: pad(m) }),
|
|
4128
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-stack", style: { gap: 3, marginLeft: 8 }, children: ["AM", "PM"].map((ap) => /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
4115
4129
|
"button",
|
|
4116
4130
|
{
|
|
4117
4131
|
type: "button",
|
|
@@ -4122,13 +4136,13 @@ function ClockFace({ value = "09:00", onChange }) {
|
|
|
4122
4136
|
ap
|
|
4123
4137
|
)) })
|
|
4124
4138
|
] }),
|
|
4125
|
-
/* @__PURE__ */ (0,
|
|
4126
|
-
/* @__PURE__ */ (0,
|
|
4127
|
-
/* @__PURE__ */ (0,
|
|
4128
|
-
minuteOff ? /* @__PURE__ */ (0,
|
|
4139
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "fd-clock", ref: faceRef, onPointerDown: down, onPointerMove: move, onPointerUp: upH, children: [
|
|
4140
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-clock-hand", style: { height: NR - (minuteOff ? 14 : 16), transform: "translateX(-50%) rotate(" + handAngle + "deg)", bottom: "50%" } }),
|
|
4141
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-clock-pivot" }),
|
|
4142
|
+
minuteOff ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { style: { position: "absolute", left: "50%", top: "50%", width: 10, height: 10, margin: -5, borderRadius: "50%", border: "2px solid var(--brand)", background: "var(--surface)", transform: "rotate(" + handAngle + "deg) translateY(-" + (NR - 6) + "px)", transformOrigin: "center", pointerEvents: "none" } }) : null,
|
|
4129
4143
|
nums.map((n) => {
|
|
4130
4144
|
const a = angleOf(n) * Math.PI / 180;
|
|
4131
|
-
return /* @__PURE__ */ (0,
|
|
4145
|
+
return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
4132
4146
|
"span",
|
|
4133
4147
|
{
|
|
4134
4148
|
className: "fd-clock-num" + (n === selNum || mode2 === "m" && n === Math.round(m / 5) * 5 % 60 && m % 5 === 0 ? " is-sel" : ""),
|
|
@@ -4139,16 +4153,17 @@ function ClockFace({ value = "09:00", onChange }) {
|
|
|
4139
4153
|
);
|
|
4140
4154
|
})
|
|
4141
4155
|
] }),
|
|
4142
|
-
/* @__PURE__ */ (0,
|
|
4156
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)("div", { className: "fd-row", style: { justifyContent: "center", gap: 6 }, children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-body-sm fd-muted", children: mode2 === "h" ? "Pick the hour \u2014 drag or tap" : "Now the minutes" }) })
|
|
4143
4157
|
] });
|
|
4144
4158
|
}
|
|
4145
|
-
function TimePicker({ label, help, error, required = false, disabled = false, value = "", onChange, placeholder = "Pick a time", className = "", style }) {
|
|
4146
|
-
const
|
|
4147
|
-
const
|
|
4148
|
-
const
|
|
4149
|
-
const
|
|
4159
|
+
function TimePicker({ label, help, error, required = false, disabled = false, value = "", onChange, placeholder = "Pick a time", id, className = "", style }) {
|
|
4160
|
+
const { fieldId, labelId, ariaLabelledBy } = useTriggerLabelling(label, id);
|
|
4161
|
+
const [open, setOpen] = React23.useState(false);
|
|
4162
|
+
const rootRef = React23.useRef(null);
|
|
4163
|
+
const boxRef = React23.useRef(null);
|
|
4164
|
+
const popRef = React23.useRef(null);
|
|
4150
4165
|
const pos = usePopPos3(open, boxRef, 420, 262);
|
|
4151
|
-
|
|
4166
|
+
React23.useEffect(() => {
|
|
4152
4167
|
if (!open) return;
|
|
4153
4168
|
const away = (e) => {
|
|
4154
4169
|
if (rootRef.current && rootRef.current.contains(e.target)) return;
|
|
@@ -4173,17 +4188,16 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
|
|
|
4173
4188
|
const toggle = () => {
|
|
4174
4189
|
if (!disabled) setOpen(!open);
|
|
4175
4190
|
};
|
|
4176
|
-
return /* @__PURE__ */ (0,
|
|
4177
|
-
label ? /* @__PURE__ */ (0,
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
/* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: ["fd-input", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : ""].filter(Boolean).join(" "), style: { cursor: disabled ? "not-allowed" : "pointer" }, onClick: toggle, ref: boxRef, children: [
|
|
4182
|
-
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "fd-input-icon", children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("i", { className: "ph ph-clock", "aria-hidden": "true" }) }),
|
|
4183
|
-
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
4191
|
+
return /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: ["fd-field", "fd-popfield", open ? "is-open" : "", className].filter(Boolean).join(" "), style, ref: rootRef, children: [
|
|
4192
|
+
label ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(FieldLabel, { id: labelId, required, onClick: toggle, children: label }) : null,
|
|
4193
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: ["fd-input", error ? "fd-input-error" : "", disabled ? "fd-input-disabled" : ""].filter(Boolean).join(" "), style: { cursor: disabled ? "not-allowed" : "pointer" }, onClick: toggle, ref: boxRef, children: [
|
|
4194
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-input-icon", children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("i", { className: "ph ph-clock", "aria-hidden": "true" }) }),
|
|
4195
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
4184
4196
|
"button",
|
|
4185
4197
|
{
|
|
4186
4198
|
type: "button",
|
|
4199
|
+
id: fieldId,
|
|
4200
|
+
"aria-labelledby": ariaLabelledBy,
|
|
4187
4201
|
disabled,
|
|
4188
4202
|
onKeyDown: (e) => {
|
|
4189
4203
|
if (e.key === "Enter" || e.key === " ") {
|
|
@@ -4195,13 +4209,13 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
|
|
|
4195
4209
|
children: disp() || placeholder
|
|
4196
4210
|
}
|
|
4197
4211
|
),
|
|
4198
|
-
/* @__PURE__ */ (0,
|
|
4212
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-select-caret", children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("i", { className: "ph ph-caret-down", "aria-hidden": "true" }) })
|
|
4199
4213
|
] }),
|
|
4200
4214
|
open && pos ? (0, import_react_dom7.createPortal)(
|
|
4201
|
-
/* @__PURE__ */ (0,
|
|
4202
|
-
/* @__PURE__ */ (0,
|
|
4203
|
-
/* @__PURE__ */ (0,
|
|
4204
|
-
/* @__PURE__ */ (0,
|
|
4215
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "fd-pop" + (pos.up ? " is-up" : ""), ref: popRef, style: popStyle3(pos, { width: 262, minWidth: 0, zIndex: 130 }), children: [
|
|
4216
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)(ClockFace, { value: value || "09:00", onChange: (v) => onChange && onChange({ target: { value: v } }) }),
|
|
4217
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "fd-cal-foot", style: { margin: "0 14px 12px", paddingTop: 10 }, children: [
|
|
4218
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
4205
4219
|
"button",
|
|
4206
4220
|
{
|
|
4207
4221
|
type: "button",
|
|
@@ -4214,22 +4228,22 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
|
|
|
4214
4228
|
children: "Now"
|
|
4215
4229
|
}
|
|
4216
4230
|
),
|
|
4217
|
-
/* @__PURE__ */ (0,
|
|
4218
|
-
/* @__PURE__ */ (0,
|
|
4231
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { style: { flex: 1 } }),
|
|
4232
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", onClick: () => setOpen(false), children: "Done" })
|
|
4219
4233
|
] })
|
|
4220
4234
|
] }),
|
|
4221
4235
|
document.body
|
|
4222
4236
|
) : null,
|
|
4223
|
-
error ? /* @__PURE__ */ (0,
|
|
4224
|
-
/* @__PURE__ */ (0,
|
|
4237
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("span", { className: "fd-field-error", children: [
|
|
4238
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
4225
4239
|
error
|
|
4226
|
-
] }) : help ? /* @__PURE__ */ (0,
|
|
4240
|
+
] }) : help ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "fd-field-help", children: help }) : null
|
|
4227
4241
|
] });
|
|
4228
4242
|
}
|
|
4229
4243
|
|
|
4230
4244
|
// src/components/forms/Slider.tsx
|
|
4231
|
-
var
|
|
4232
|
-
var
|
|
4245
|
+
var React24 = __toESM(require("react"), 1);
|
|
4246
|
+
var import_jsx_runtime53 = require("react/jsx-runtime");
|
|
4233
4247
|
function Slider({
|
|
4234
4248
|
label,
|
|
4235
4249
|
min = 0,
|
|
@@ -4240,23 +4254,27 @@ function Slider({
|
|
|
4240
4254
|
format = (v) => String(v),
|
|
4241
4255
|
showChip = true,
|
|
4242
4256
|
help,
|
|
4257
|
+
id,
|
|
4258
|
+
"aria-label": ariaLabel,
|
|
4243
4259
|
className = "",
|
|
4244
4260
|
...rest
|
|
4245
4261
|
}) {
|
|
4246
|
-
const
|
|
4262
|
+
const fieldId = useFieldId(id);
|
|
4263
|
+
const [dragging, setDragging] = React24.useState(false);
|
|
4247
4264
|
const v = value === void 0 ? min : Number(value);
|
|
4248
4265
|
const pct = max === min ? 0 : (v - min) / (max - min) * 100;
|
|
4249
|
-
return /* @__PURE__ */ (0,
|
|
4250
|
-
label ? /* @__PURE__ */ (0,
|
|
4251
|
-
/* @__PURE__ */ (0,
|
|
4252
|
-
/* @__PURE__ */ (0,
|
|
4266
|
+
return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: ["fd-field", className].filter(Boolean).join(" "), children: [
|
|
4267
|
+
label ? /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
|
|
4268
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(FieldLabel, { htmlFor: fieldId, children: label }),
|
|
4269
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { className: "fd-num", style: { color: "var(--text-2)" }, children: format(v) })
|
|
4253
4270
|
] }) : null,
|
|
4254
|
-
/* @__PURE__ */ (0,
|
|
4255
|
-
/* @__PURE__ */ (0,
|
|
4256
|
-
showChip && dragging ? /* @__PURE__ */ (0,
|
|
4257
|
-
/* @__PURE__ */ (0,
|
|
4271
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "fd-slider", children: [
|
|
4272
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
|
|
4273
|
+
showChip && dragging ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { className: "fd-slider-chip", style: { left: pct + "%" }, children: format(v) }) : null,
|
|
4274
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
4258
4275
|
"input",
|
|
4259
4276
|
{
|
|
4277
|
+
id: fieldId,
|
|
4260
4278
|
type: "range",
|
|
4261
4279
|
min,
|
|
4262
4280
|
max,
|
|
@@ -4266,18 +4284,18 @@ function Slider({
|
|
|
4266
4284
|
onPointerDown: () => setDragging(true),
|
|
4267
4285
|
onPointerUp: () => setDragging(false),
|
|
4268
4286
|
onBlur: () => setDragging(false),
|
|
4269
|
-
"aria-label":
|
|
4287
|
+
"aria-label": ariaLabel,
|
|
4270
4288
|
...rest
|
|
4271
4289
|
}
|
|
4272
4290
|
)
|
|
4273
4291
|
] }),
|
|
4274
|
-
help ? /* @__PURE__ */ (0,
|
|
4292
|
+
help ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { className: "fd-field-help", children: help }) : null
|
|
4275
4293
|
] });
|
|
4276
4294
|
}
|
|
4277
4295
|
|
|
4278
4296
|
// src/components/forms/RangeSlider.tsx
|
|
4279
|
-
var
|
|
4280
|
-
var
|
|
4297
|
+
var React25 = __toESM(require("react"), 1);
|
|
4298
|
+
var import_jsx_runtime54 = require("react/jsx-runtime");
|
|
4281
4299
|
function RangeSlider({
|
|
4282
4300
|
label,
|
|
4283
4301
|
min = 0,
|
|
@@ -4296,9 +4314,9 @@ function RangeSlider({
|
|
|
4296
4314
|
}) {
|
|
4297
4315
|
const fmt2 = format || ((v) => String(v));
|
|
4298
4316
|
const [a, b] = value || [min, max];
|
|
4299
|
-
const [drag, setDrag] =
|
|
4300
|
-
const [focus, setFocus] =
|
|
4301
|
-
const railRef =
|
|
4317
|
+
const [drag, setDrag] = React25.useState(null);
|
|
4318
|
+
const [focus, setFocus] = React25.useState(null);
|
|
4319
|
+
const railRef = React25.useRef(null);
|
|
4302
4320
|
const pct = (v) => max === min ? 0 : (v - min) / (max - min) * 100;
|
|
4303
4321
|
const clampPair = (i, v) => {
|
|
4304
4322
|
v = Math.min(max, Math.max(min, Math.round(v / step) * step));
|
|
@@ -4313,7 +4331,7 @@ function RangeSlider({
|
|
|
4313
4331
|
const r = railRef.current.getBoundingClientRect();
|
|
4314
4332
|
return min + Math.min(1, Math.max(0, (e.clientX - r.left) / r.width)) * (max - min);
|
|
4315
4333
|
};
|
|
4316
|
-
|
|
4334
|
+
React25.useEffect(() => {
|
|
4317
4335
|
if (drag === null) return;
|
|
4318
4336
|
const mv = (e) => onChange && onChange(clampPair(drag, fromEvent(e)));
|
|
4319
4337
|
const upH = () => setDrag(null);
|
|
@@ -4334,7 +4352,7 @@ function RangeSlider({
|
|
|
4334
4352
|
};
|
|
4335
4353
|
const thin = S.length > 7 ? Math.ceil(S.length / 5) : 1;
|
|
4336
4354
|
const pair = value || [S[0].value, S[S.length - 1].value];
|
|
4337
|
-
return /* @__PURE__ */ (0,
|
|
4355
|
+
return /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
|
|
4338
4356
|
RangeSlider,
|
|
4339
4357
|
{
|
|
4340
4358
|
...rest,
|
|
@@ -4382,23 +4400,23 @@ function RangeSlider({
|
|
|
4382
4400
|
};
|
|
4383
4401
|
const showChip = (i) => drag === i || focus === i;
|
|
4384
4402
|
const hasLabels = marks.some((m) => m.label);
|
|
4385
|
-
return /* @__PURE__ */ (0,
|
|
4386
|
-
label ? /* @__PURE__ */ (0,
|
|
4387
|
-
/* @__PURE__ */ (0,
|
|
4388
|
-
/* @__PURE__ */ (0,
|
|
4403
|
+
return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: ["fd-field", className].filter(Boolean).join(" "), ...rest, children: [
|
|
4404
|
+
label ? /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
|
|
4405
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-field-label", children: label }),
|
|
4406
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("span", { className: "fd-num", style: { color: "var(--text-2)" }, children: [
|
|
4389
4407
|
fmt2(a),
|
|
4390
4408
|
" \u2013 ",
|
|
4391
4409
|
fmt2(b)
|
|
4392
4410
|
] })
|
|
4393
4411
|
] }) : null,
|
|
4394
|
-
/* @__PURE__ */ (0,
|
|
4395
|
-
/* @__PURE__ */ (0,
|
|
4396
|
-
/* @__PURE__ */ (0,
|
|
4397
|
-
marks.map((m) => /* @__PURE__ */ (0,
|
|
4398
|
-
/* @__PURE__ */ (0,
|
|
4399
|
-
m.label ? /* @__PURE__ */ (0,
|
|
4412
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "fd-range" + (hasLabels ? " has-labels" : ""), onPointerDown: onRailDown, children: [
|
|
4413
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-range-rail", ref: railRef }),
|
|
4414
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-range-fill", style: { left: pct(a) + "%", width: pct(b) - pct(a) + "%" } }),
|
|
4415
|
+
marks.map((m) => /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(React25.Fragment, { children: [
|
|
4416
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-range-mark" + (m.value >= a && m.value <= b ? " is-in" : ""), style: { left: pct(m.value) + "%" } }),
|
|
4417
|
+
m.label ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-range-mark-label", style: { left: pct(m.value) + "%" }, children: m.label }) : null
|
|
4400
4418
|
] }, m.value)),
|
|
4401
|
-
[a, b].map((v, i) => /* @__PURE__ */ (0,
|
|
4419
|
+
[a, b].map((v, i) => /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
|
|
4402
4420
|
"span",
|
|
4403
4421
|
{
|
|
4404
4422
|
className: "fd-range-thumb" + (drag === i ? " is-drag" : ""),
|
|
@@ -4413,18 +4431,18 @@ function RangeSlider({
|
|
|
4413
4431
|
onKeyDown: key(i),
|
|
4414
4432
|
onFocus: () => setFocus(i),
|
|
4415
4433
|
onBlur: () => setFocus(null),
|
|
4416
|
-
children: /* @__PURE__ */ (0,
|
|
4434
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-range-chip", style: { opacity: showChip(i) ? 1 : void 0 }, children: fmt2(v) })
|
|
4417
4435
|
},
|
|
4418
4436
|
i
|
|
4419
4437
|
))
|
|
4420
4438
|
] }),
|
|
4421
|
-
help ? /* @__PURE__ */ (0,
|
|
4439
|
+
help ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "fd-field-help", children: help }) : null
|
|
4422
4440
|
] });
|
|
4423
4441
|
}
|
|
4424
4442
|
|
|
4425
4443
|
// src/components/forms/Dropzone.tsx
|
|
4426
|
-
var
|
|
4427
|
-
var
|
|
4444
|
+
var React26 = __toESM(require("react"), 1);
|
|
4445
|
+
var import_jsx_runtime55 = require("react/jsx-runtime");
|
|
4428
4446
|
function Dropzone({
|
|
4429
4447
|
onFiles,
|
|
4430
4448
|
onReject,
|
|
@@ -4438,8 +4456,8 @@ function Dropzone({
|
|
|
4438
4456
|
className = "",
|
|
4439
4457
|
style
|
|
4440
4458
|
}) {
|
|
4441
|
-
const [over, setOver] =
|
|
4442
|
-
const depth =
|
|
4459
|
+
const [over, setOver] = React26.useState(false);
|
|
4460
|
+
const depth = React26.useRef(0);
|
|
4443
4461
|
const has = (e) => {
|
|
4444
4462
|
const dt = e.dataTransfer;
|
|
4445
4463
|
if (!dt) return false;
|
|
@@ -4469,7 +4487,7 @@ function Dropzone({
|
|
|
4469
4487
|
if (rejected.length && onReject) onReject(rejected);
|
|
4470
4488
|
if (accepted.length && onFiles) onFiles(accepted);
|
|
4471
4489
|
};
|
|
4472
|
-
return /* @__PURE__ */ (0,
|
|
4490
|
+
return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(
|
|
4473
4491
|
"div",
|
|
4474
4492
|
{
|
|
4475
4493
|
className: ["fd-dropzone", over ? "is-over" : "", className].filter(Boolean).join(" "),
|
|
@@ -4480,10 +4498,10 @@ function Dropzone({
|
|
|
4480
4498
|
onDrop: drop,
|
|
4481
4499
|
children: [
|
|
4482
4500
|
children,
|
|
4483
|
-
over ? /* @__PURE__ */ (0,
|
|
4484
|
-
/* @__PURE__ */ (0,
|
|
4485
|
-
/* @__PURE__ */ (0,
|
|
4486
|
-
hint ? /* @__PURE__ */ (0,
|
|
4501
|
+
over ? /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: "fd-dropzone-veil", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "fd-dropzone-card", children: [
|
|
4502
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)("i", { className: "ph ph-tray-arrow-down" }),
|
|
4503
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "fd-dropzone-label", children: label }),
|
|
4504
|
+
hint ? /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "fd-dropzone-hint", children: hint }) : null
|
|
4487
4505
|
] }) }) : null
|
|
4488
4506
|
]
|
|
4489
4507
|
}
|
|
@@ -4501,9 +4519,9 @@ function FilePickButton({
|
|
|
4501
4519
|
className = "",
|
|
4502
4520
|
children
|
|
4503
4521
|
}) {
|
|
4504
|
-
const ref =
|
|
4505
|
-
return /* @__PURE__ */ (0,
|
|
4506
|
-
/* @__PURE__ */ (0,
|
|
4522
|
+
const ref = React26.useRef(null);
|
|
4523
|
+
return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(React26.Fragment, { children: [
|
|
4524
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
|
|
4507
4525
|
"button",
|
|
4508
4526
|
{
|
|
4509
4527
|
type: "button",
|
|
@@ -4512,10 +4530,10 @@ function FilePickButton({
|
|
|
4512
4530
|
"aria-label": label,
|
|
4513
4531
|
title: label,
|
|
4514
4532
|
onClick: () => ref.current && ref.current.click(),
|
|
4515
|
-
children: children != null ? children : /* @__PURE__ */ (0,
|
|
4533
|
+
children: children != null ? children : /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("i", { className: "ph ph-" + icon, "aria-hidden": "true" })
|
|
4516
4534
|
}
|
|
4517
4535
|
),
|
|
4518
|
-
/* @__PURE__ */ (0,
|
|
4536
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
|
|
4519
4537
|
"input",
|
|
4520
4538
|
{
|
|
4521
4539
|
ref,
|
|
@@ -4535,10 +4553,10 @@ function FilePickButton({
|
|
|
4535
4553
|
}
|
|
4536
4554
|
function useStagedFiles(upload, opts) {
|
|
4537
4555
|
const o = opts || {};
|
|
4538
|
-
const [items, setItems] =
|
|
4539
|
-
const controllers =
|
|
4556
|
+
const [items, setItems] = React26.useState([]);
|
|
4557
|
+
const controllers = React26.useRef({});
|
|
4540
4558
|
const patch = (id, next) => setItems((list) => list.map((f) => f.id === id ? Object.assign({}, f, next) : f));
|
|
4541
|
-
const run =
|
|
4559
|
+
const run = React26.useCallback((att) => {
|
|
4542
4560
|
if (!upload) return;
|
|
4543
4561
|
const ac = typeof AbortController !== "undefined" ? new AbortController() : null;
|
|
4544
4562
|
controllers.current[att.id] = ac;
|
|
@@ -4555,14 +4573,14 @@ function useStagedFiles(upload, opts) {
|
|
|
4555
4573
|
delete controllers.current[att.id];
|
|
4556
4574
|
});
|
|
4557
4575
|
}, [upload]);
|
|
4558
|
-
const add =
|
|
4576
|
+
const add = React26.useCallback((files) => {
|
|
4559
4577
|
if (!upload) return [];
|
|
4560
4578
|
const atts = Array.from(files).map((f) => toAttachment(f));
|
|
4561
4579
|
setItems((list) => list.concat(atts));
|
|
4562
4580
|
atts.forEach(run);
|
|
4563
4581
|
return atts;
|
|
4564
4582
|
}, [upload, run]);
|
|
4565
|
-
const remove =
|
|
4583
|
+
const remove = React26.useCallback((att) => {
|
|
4566
4584
|
const ac = controllers.current[att.id];
|
|
4567
4585
|
if (ac) {
|
|
4568
4586
|
try {
|
|
@@ -4573,10 +4591,10 @@ function useStagedFiles(upload, opts) {
|
|
|
4573
4591
|
}
|
|
4574
4592
|
setItems((list) => list.filter((f) => f.id !== att.id));
|
|
4575
4593
|
}, []);
|
|
4576
|
-
const retry =
|
|
4594
|
+
const retry = React26.useCallback((att) => {
|
|
4577
4595
|
run(att);
|
|
4578
4596
|
}, [run]);
|
|
4579
|
-
const clear =
|
|
4597
|
+
const clear = React26.useCallback(() => {
|
|
4580
4598
|
Object.values(controllers.current).forEach((ac) => {
|
|
4581
4599
|
try {
|
|
4582
4600
|
ac && ac.abort();
|
|
@@ -4592,7 +4610,7 @@ function useStagedFiles(upload, opts) {
|
|
|
4592
4610
|
var DropzoneKit = { useStagedFiles };
|
|
4593
4611
|
|
|
4594
4612
|
// src/components/forms/FileGrid.tsx
|
|
4595
|
-
var
|
|
4613
|
+
var import_jsx_runtime56 = require("react/jsx-runtime");
|
|
4596
4614
|
var truncateMiddle = (name, max = 34) => {
|
|
4597
4615
|
if (!name || name.length <= max) return name;
|
|
4598
4616
|
const ext = /\.[A-Za-z0-9]+$/.exec(name);
|
|
@@ -4601,7 +4619,7 @@ var truncateMiddle = (name, max = 34) => {
|
|
|
4601
4619
|
return head + "\u2026" + tail;
|
|
4602
4620
|
};
|
|
4603
4621
|
function Progress({ value }) {
|
|
4604
|
-
return /* @__PURE__ */ (0,
|
|
4622
|
+
return /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-file-prog", role: "progressbar", "aria-valuenow": Math.round(value), "aria-valuemin": 0, "aria-valuemax": 100, children: /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-file-prog-fill", style: { width: Math.max(4, Math.min(100, value)) + "%" } }) });
|
|
4605
4623
|
}
|
|
4606
4624
|
function FileChip({ file, onOpen, onRemove, onRetry, compact: compact3 = false, className = "" }) {
|
|
4607
4625
|
if (!file) return null;
|
|
@@ -4610,8 +4628,8 @@ function FileChip({ file, onOpen, onRemove, onRetry, compact: compact3 = false,
|
|
|
4610
4628
|
const thumb = file.thumb && file.thumb.url || (image ? file.blobUrl || file.url : null);
|
|
4611
4629
|
const meta = file.meta || (file.size ? formatBytes(file.size) : "");
|
|
4612
4630
|
const clickable = !!onOpen && !uploading;
|
|
4613
|
-
return /* @__PURE__ */ (0,
|
|
4614
|
-
/* @__PURE__ */ (0,
|
|
4631
|
+
return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: ["fd-file", compact3 ? "is-compact" : "", file.error ? "is-error" : "", uploading ? "is-uploading" : "", className].filter(Boolean).join(" "), children: [
|
|
4632
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(
|
|
4615
4633
|
"button",
|
|
4616
4634
|
{
|
|
4617
4635
|
type: "button",
|
|
@@ -4620,16 +4638,16 @@ function FileChip({ file, onOpen, onRemove, onRetry, compact: compact3 = false,
|
|
|
4620
4638
|
onClick: clickable ? () => onOpen(file) : void 0,
|
|
4621
4639
|
title: file.name + (meta ? " \xB7 " + meta : ""),
|
|
4622
4640
|
children: [
|
|
4623
|
-
/* @__PURE__ */ (0,
|
|
4624
|
-
thumb ? /* @__PURE__ */ (0,
|
|
4625
|
-
(file.mime || "").startsWith("video/") ? /* @__PURE__ */ (0,
|
|
4641
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("span", { className: "fd-file-icon", children: [
|
|
4642
|
+
thumb ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("img", { src: thumb, alt: "" }) : /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("i", { className: "ph ph-" + iconForMime(file.mime, file.name), "aria-hidden": "true" }),
|
|
4643
|
+
(file.mime || "").startsWith("video/") ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("i", { className: "ph ph-play fd-file-play", "aria-hidden": "true" }) : null
|
|
4626
4644
|
] }),
|
|
4627
|
-
/* @__PURE__ */ (0,
|
|
4628
|
-
/* @__PURE__ */ (0,
|
|
4629
|
-
/* @__PURE__ */ (0,
|
|
4630
|
-
/* @__PURE__ */ (0,
|
|
4645
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("span", { className: "fd-file-text", children: [
|
|
4646
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-file-name", children: truncateMiddle(file.name, compact3 ? 26 : 40) }),
|
|
4647
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-file-meta", children: file.error ? /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("span", { className: "fd-file-err", children: [
|
|
4648
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
4631
4649
|
file.error
|
|
4632
|
-
] }) : uploading ? /* @__PURE__ */ (0,
|
|
4650
|
+
] }) : uploading ? /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("span", { className: "fd-tabular", children: [
|
|
4633
4651
|
Math.round(file.progress),
|
|
4634
4652
|
"% uploaded"
|
|
4635
4653
|
] }) : meta })
|
|
@@ -4637,29 +4655,29 @@ function FileChip({ file, onOpen, onRemove, onRetry, compact: compact3 = false,
|
|
|
4637
4655
|
]
|
|
4638
4656
|
}
|
|
4639
4657
|
),
|
|
4640
|
-
uploading ? /* @__PURE__ */ (0,
|
|
4641
|
-
file.error && onRetry ? /* @__PURE__ */ (0,
|
|
4642
|
-
onRemove ? /* @__PURE__ */ (0,
|
|
4658
|
+
uploading ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Progress, { value: file.progress }) : null,
|
|
4659
|
+
file.error && onRetry ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("button", { type: "button", className: "fd-file-act", onClick: () => onRetry(file), "aria-label": "Retry upload of " + file.name, children: /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
|
|
4660
|
+
onRemove ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("button", { type: "button", className: "fd-file-act", onClick: () => onRemove(file), "aria-label": "Remove " + file.name, children: /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
|
|
4643
4661
|
] });
|
|
4644
4662
|
}
|
|
4645
4663
|
function FileTile({ file, onOpen, onRemove, maxHeight = 200, className = "" }) {
|
|
4646
4664
|
if (!file) return null;
|
|
4647
4665
|
const src = file.thumb && file.thumb.url || file.blobUrl || file.url;
|
|
4648
4666
|
const uploading = file.progress != null && file.progress < 100 && !file.error;
|
|
4649
|
-
return /* @__PURE__ */ (0,
|
|
4650
|
-
/* @__PURE__ */ (0,
|
|
4651
|
-
uploading ? /* @__PURE__ */ (0,
|
|
4652
|
-
file.error ? /* @__PURE__ */ (0,
|
|
4653
|
-
/* @__PURE__ */ (0,
|
|
4667
|
+
return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("figure", { className: ["fd-tile", uploading ? "is-uploading" : "", file.error ? "is-error" : "", className].filter(Boolean).join(" "), children: [
|
|
4668
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("button", { type: "button", className: "fd-tile-btn", onClick: onOpen ? () => onOpen(file) : void 0, disabled: !onOpen, children: src ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("img", { src, alt: file.name || "", style: { maxHeight }, loading: "lazy" }) : /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-tile-fallback", children: /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("i", { className: "ph ph-" + iconForMime(file.mime, file.name), "aria-hidden": "true" }) }) }),
|
|
4669
|
+
uploading ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Progress, { value: file.progress }) : null,
|
|
4670
|
+
file.error ? /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("figcaption", { className: "fd-tile-err", children: [
|
|
4671
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
4654
4672
|
file.error
|
|
4655
4673
|
] }) : null,
|
|
4656
|
-
onRemove ? /* @__PURE__ */ (0,
|
|
4674
|
+
onRemove ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("button", { type: "button", className: "fd-tile-x", onClick: () => onRemove(file), "aria-label": "Remove " + file.name, children: /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
|
|
4657
4675
|
] });
|
|
4658
4676
|
}
|
|
4659
4677
|
function FileStrip({ files = [], size = 68, onOpen, onRemove, onRetry, className = "" }) {
|
|
4660
4678
|
const list = files.filter(Boolean);
|
|
4661
4679
|
if (!list.length) return null;
|
|
4662
|
-
return /* @__PURE__ */ (0,
|
|
4680
|
+
return /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: ["fd-filestrip", "fd-scrollbar", className].filter(Boolean).join(" "), style: { "--fd-cell": size + "px" }, children: list.map((f) => /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(FileCell, { file: f, onOpen, onRemove, onRetry }, f.id || f.name)) });
|
|
4663
4681
|
}
|
|
4664
4682
|
var shortName = (name, keep = 5) => {
|
|
4665
4683
|
const s = String(name || "file");
|
|
@@ -4673,19 +4691,19 @@ function FileCell({ file, onOpen, onRemove, onRetry }) {
|
|
|
4673
4691
|
const image = isImage(file.mime, file.name);
|
|
4674
4692
|
const thumb = file.thumb && file.thumb.url || (image ? file.blobUrl || file.url : null);
|
|
4675
4693
|
const label = file.name + (file.size ? " \xB7 " + formatBytes(file.size) : "");
|
|
4676
|
-
return /* @__PURE__ */ (0,
|
|
4677
|
-
/* @__PURE__ */ (0,
|
|
4678
|
-
thumb ? /* @__PURE__ */ (0,
|
|
4679
|
-
/* @__PURE__ */ (0,
|
|
4680
|
-
/* @__PURE__ */ (0,
|
|
4681
|
-
/* @__PURE__ */ (0,
|
|
4694
|
+
return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: ["fd-cell", file.error ? "is-error" : "", uploading ? "is-uploading" : ""].filter(Boolean).join(" "), title: file.error ? file.name + " \u2014 " + file.error : label, children: [
|
|
4695
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("button", { type: "button", className: "fd-cell-main", onClick: onOpen ? () => onOpen(file) : void 0, disabled: !onOpen || uploading, "aria-label": "Open " + file.name, children: [
|
|
4696
|
+
thumb ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("img", { src: thumb, alt: "" }) : /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("span", { className: "fd-cell-doc", children: [
|
|
4697
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("i", { className: "ph ph-" + iconForMime(file.mime, file.name), "aria-hidden": "true" }),
|
|
4698
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-cell-name", children: shortName(file.name) }),
|
|
4699
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-cell-size", children: file.meta || formatBytes(file.size) })
|
|
4682
4700
|
] }),
|
|
4683
|
-
(file.mime || "").startsWith("video/") ? /* @__PURE__ */ (0,
|
|
4701
|
+
(file.mime || "").startsWith("video/") ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("i", { className: "ph ph-play fd-cell-play", "aria-hidden": "true" }) : null
|
|
4684
4702
|
] }),
|
|
4685
|
-
uploading ? /* @__PURE__ */ (0,
|
|
4686
|
-
file.error ? /* @__PURE__ */ (0,
|
|
4687
|
-
file.error && onRetry ? /* @__PURE__ */ (0,
|
|
4688
|
-
onRemove ? /* @__PURE__ */ (0,
|
|
4703
|
+
uploading ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Progress, { value: file.progress }) : null,
|
|
4704
|
+
file.error ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "fd-cell-err", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("i", { className: "ph ph-warning-circle" }) }) : null,
|
|
4705
|
+
file.error && onRetry ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("button", { type: "button", className: "fd-cell-x is-retry", onClick: () => onRetry(file), "aria-label": "Retry upload of " + file.name, children: /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
|
|
4706
|
+
onRemove ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("button", { type: "button", className: "fd-cell-x", onClick: () => onRemove(file), "aria-label": "Remove " + file.name, children: /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
|
|
4689
4707
|
] });
|
|
4690
4708
|
}
|
|
4691
4709
|
function FileGrid({ files = [], onOpen, onRemove, onRetry, tiles = true, maxHeight = 200, compact: compact3 = false, className = "" }) {
|
|
@@ -4693,15 +4711,15 @@ function FileGrid({ files = [], onOpen, onRemove, onRetry, tiles = true, maxHeig
|
|
|
4693
4711
|
if (!list.length) return null;
|
|
4694
4712
|
const pics = tiles ? list.filter((f) => isImage(f.mime, f.name)) : [];
|
|
4695
4713
|
const rest = list.filter((f) => pics.indexOf(f) === -1);
|
|
4696
|
-
return /* @__PURE__ */ (0,
|
|
4697
|
-
pics.length ? /* @__PURE__ */ (0,
|
|
4698
|
-
rest.length ? /* @__PURE__ */ (0,
|
|
4714
|
+
return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: ["fd-filegrid", className].filter(Boolean).join(" "), children: [
|
|
4715
|
+
pics.length ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: "fd-filegrid-tiles", children: pics.map((f) => /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(FileTile, { file: f, onOpen, onRemove, maxHeight }, f.id || f.name)) }) : null,
|
|
4716
|
+
rest.length ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: "fd-filegrid-chips", children: rest.map((f) => /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(FileChip, { file: f, onOpen, onRemove, onRetry, compact: compact3 }, f.id || f.name)) }) : null
|
|
4699
4717
|
] });
|
|
4700
4718
|
}
|
|
4701
4719
|
|
|
4702
4720
|
// src/components/forms/MarkdownEditor.tsx
|
|
4703
|
-
var
|
|
4704
|
-
var
|
|
4721
|
+
var React27 = __toESM(require("react"), 1);
|
|
4722
|
+
var import_jsx_runtime57 = require("react/jsx-runtime");
|
|
4705
4723
|
var isMac = typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent || "");
|
|
4706
4724
|
var INLINE_RE = /(\*\*\*[^*\n]+\*\*\*|\*\*[^*\n]+\*\*|__[^_\n]+__|~~[^~\n]+~~|`[^`\n]+`|\*[^*\s][^*\n]*\*|(?<![A-Za-z0-9_])_[^_\s][^_\n]*_|\[[^\]\n]*\]\([^)\s\n]*\)|https?:\/\/\S+)/g;
|
|
4707
4725
|
function inlineParts(text) {
|
|
@@ -4914,7 +4932,7 @@ function syncDom(root, value) {
|
|
|
4914
4932
|
while (root.children.length > lines.length) root.removeChild(root.lastChild);
|
|
4915
4933
|
}
|
|
4916
4934
|
var LIST_CONT = RE_LI;
|
|
4917
|
-
var MarkdownEditor =
|
|
4935
|
+
var MarkdownEditor = React27.forwardRef(function MarkdownEditor2({
|
|
4918
4936
|
value = "",
|
|
4919
4937
|
onChange,
|
|
4920
4938
|
onSubmit,
|
|
@@ -4933,10 +4951,10 @@ var MarkdownEditor = React26.forwardRef(function MarkdownEditor2({
|
|
|
4933
4951
|
className = "",
|
|
4934
4952
|
id
|
|
4935
4953
|
}, ref) {
|
|
4936
|
-
const boxRef =
|
|
4937
|
-
const composing =
|
|
4938
|
-
const pendingCaret =
|
|
4939
|
-
|
|
4954
|
+
const boxRef = React27.useRef(null);
|
|
4955
|
+
const composing = React27.useRef(false);
|
|
4956
|
+
const pendingCaret = React27.useRef(null);
|
|
4957
|
+
React27.useLayoutEffect(() => {
|
|
4940
4958
|
const root = boxRef.current;
|
|
4941
4959
|
if (!root || composing.current) return;
|
|
4942
4960
|
const active = document.activeElement === root || root.contains(document.activeElement);
|
|
@@ -4945,7 +4963,7 @@ var MarkdownEditor = React26.forwardRef(function MarkdownEditor2({
|
|
|
4945
4963
|
pendingCaret.current = null;
|
|
4946
4964
|
if (active && caret != null) placeCaret(root, caret);
|
|
4947
4965
|
}, [value]);
|
|
4948
|
-
|
|
4966
|
+
React27.useEffect(() => {
|
|
4949
4967
|
if (autoFocus && boxRef.current) boxRef.current.focus();
|
|
4950
4968
|
}, [autoFocus]);
|
|
4951
4969
|
const caretNow = () => {
|
|
@@ -5012,7 +5030,7 @@ var MarkdownEditor = React26.forwardRef(function MarkdownEditor2({
|
|
|
5012
5030
|
api.replaceRange(from, to, next, from + next.length);
|
|
5013
5031
|
}
|
|
5014
5032
|
};
|
|
5015
|
-
|
|
5033
|
+
React27.useImperativeHandle(ref, () => api);
|
|
5016
5034
|
function detect(text, caret) {
|
|
5017
5035
|
if (!onTrigger) return;
|
|
5018
5036
|
const upto = text.slice(0, caret);
|
|
@@ -5125,8 +5143,8 @@ var MarkdownEditor = React26.forwardRef(function MarkdownEditor2({
|
|
|
5125
5143
|
api.replaceRange(s.start, s.end, text.replace(/\r\n?/g, "\n"));
|
|
5126
5144
|
};
|
|
5127
5145
|
const lh = 1.55;
|
|
5128
|
-
return /* @__PURE__ */ (0,
|
|
5129
|
-
/* @__PURE__ */ (0,
|
|
5146
|
+
return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: ["fd-rme-wrap", disabled ? "is-disabled" : "", className].filter(Boolean).join(" "), children: [
|
|
5147
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
5130
5148
|
"div",
|
|
5131
5149
|
{
|
|
5132
5150
|
ref: boxRef,
|
|
@@ -5159,15 +5177,15 @@ var MarkdownEditor = React26.forwardRef(function MarkdownEditor2({
|
|
|
5159
5177
|
}
|
|
5160
5178
|
}
|
|
5161
5179
|
),
|
|
5162
|
-
!value ? /* @__PURE__ */ (0,
|
|
5180
|
+
!value ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "fd-rme-ph", "aria-hidden": "true", children: placeholder }) : null
|
|
5163
5181
|
] });
|
|
5164
5182
|
});
|
|
5165
5183
|
|
|
5166
5184
|
// src/components/platform/AccountMenu.tsx
|
|
5167
|
-
var
|
|
5185
|
+
var React29 = __toESM(require("react"), 1);
|
|
5168
5186
|
|
|
5169
5187
|
// src/kits/session.ts
|
|
5170
|
-
var
|
|
5188
|
+
var React28 = __toESM(require("react"), 1);
|
|
5171
5189
|
var PERMISSION_CATALOG = [
|
|
5172
5190
|
{ group: "Plans", items: [
|
|
5173
5191
|
{ key: "plan.view", label: "View plans", detail: "Read any plan in the workspace." },
|
|
@@ -6734,8 +6752,8 @@ function roadmap(overrides) {
|
|
|
6734
6752
|
};
|
|
6735
6753
|
}
|
|
6736
6754
|
function useSession() {
|
|
6737
|
-
const [s, setS] =
|
|
6738
|
-
|
|
6755
|
+
const [s, setS] = React28.useState(getSession);
|
|
6756
|
+
React28.useEffect(() => subscribe(setS), []);
|
|
6739
6757
|
return s;
|
|
6740
6758
|
}
|
|
6741
6759
|
var SessionKit = {
|
|
@@ -6768,7 +6786,7 @@ var SessionKit = {
|
|
|
6768
6786
|
};
|
|
6769
6787
|
|
|
6770
6788
|
// src/components/platform/AccountMenu.tsx
|
|
6771
|
-
var
|
|
6789
|
+
var import_jsx_runtime58 = require("react/jsx-runtime");
|
|
6772
6790
|
var DEFAULT_LINKS = [
|
|
6773
6791
|
{ id: "profile", label: "Your profile", icon: "user-circle", href: "../admin/index.html#profile" },
|
|
6774
6792
|
{ id: "preferences", label: "Preferences", icon: "sliders-horizontal", href: "../admin/index.html#preferences" }
|
|
@@ -6779,7 +6797,7 @@ var DEFAULT_ADMIN_LINKS = [
|
|
|
6779
6797
|
{ id: "flags", label: "Feature flags", icon: "toggle-right", href: "../admin/index.html#flags", perm: "flags.manage" }
|
|
6780
6798
|
];
|
|
6781
6799
|
function Item({ item, onPick }) {
|
|
6782
|
-
return /* @__PURE__ */ (0,
|
|
6800
|
+
return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
|
|
6783
6801
|
"button",
|
|
6784
6802
|
{
|
|
6785
6803
|
type: "button",
|
|
@@ -6787,9 +6805,9 @@ function Item({ item, onPick }) {
|
|
|
6787
6805
|
className: "fd-acct-item",
|
|
6788
6806
|
onClick: () => onPick(item),
|
|
6789
6807
|
children: [
|
|
6790
|
-
/* @__PURE__ */ (0,
|
|
6791
|
-
/* @__PURE__ */ (0,
|
|
6792
|
-
item.badge ? /* @__PURE__ */ (0,
|
|
6808
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("i", { className: "ph ph-" + item.icon, "aria-hidden": "true" }),
|
|
6809
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { style: { flex: 1 }, children: item.label }),
|
|
6810
|
+
item.badge ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Badge, { tone: "neutral", children: item.badge }) : null
|
|
6793
6811
|
]
|
|
6794
6812
|
}
|
|
6795
6813
|
);
|
|
@@ -6805,9 +6823,9 @@ function AccountMenu({
|
|
|
6805
6823
|
...rest
|
|
6806
6824
|
}) {
|
|
6807
6825
|
const session = SessionKit.useSession();
|
|
6808
|
-
const [open, setOpen] =
|
|
6809
|
-
const [switching, setSwitching] =
|
|
6810
|
-
const ref =
|
|
6826
|
+
const [open, setOpen] = React29.useState(false);
|
|
6827
|
+
const [switching, setSwitching] = React29.useState(false);
|
|
6828
|
+
const ref = React29.useRef(null);
|
|
6811
6829
|
const user = session.user;
|
|
6812
6830
|
const visibleAdmin = adminLinks.filter((l) => !l.perm || SessionKit.can(l.perm));
|
|
6813
6831
|
const pick = (item) => {
|
|
@@ -6821,8 +6839,8 @@ function AccountMenu({
|
|
|
6821
6839
|
if (onSignOut) return onSignOut();
|
|
6822
6840
|
window.alert("Signed out. (Simulated \u2014 no auth provider is wired up.)");
|
|
6823
6841
|
};
|
|
6824
|
-
return /* @__PURE__ */ (0,
|
|
6825
|
-
/* @__PURE__ */ (0,
|
|
6842
|
+
return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(import_jsx_runtime58.Fragment, { children: [
|
|
6843
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
|
|
6826
6844
|
"button",
|
|
6827
6845
|
{
|
|
6828
6846
|
type: "button",
|
|
@@ -6834,32 +6852,32 @@ function AccountMenu({
|
|
|
6834
6852
|
onClick: () => setOpen((o) => !o),
|
|
6835
6853
|
...rest,
|
|
6836
6854
|
children: [
|
|
6837
|
-
/* @__PURE__ */ (0,
|
|
6838
|
-
/* @__PURE__ */ (0,
|
|
6855
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Avatar, { name: user.name, size: "sm" }),
|
|
6856
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("i", { className: "ph ph-caret-down", "aria-hidden": "true", style: { fontSize: 11, color: "var(--text-muted)" } })
|
|
6839
6857
|
]
|
|
6840
6858
|
}
|
|
6841
6859
|
),
|
|
6842
|
-
/* @__PURE__ */ (0,
|
|
6843
|
-
/* @__PURE__ */ (0,
|
|
6844
|
-
/* @__PURE__ */ (0,
|
|
6845
|
-
/* @__PURE__ */ (0,
|
|
6846
|
-
/* @__PURE__ */ (0,
|
|
6847
|
-
/* @__PURE__ */ (0,
|
|
6860
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Popover, { open, anchorRef: ref, onClose: () => setOpen(false), placement: "bottom-end", width: 272, children: /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { role: "menu", className: "fd-stack", style: { gap: 0 }, children: [
|
|
6861
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
|
|
6862
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Avatar, { name: user.name }),
|
|
6863
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "fd-stack", style: { gap: 1, minWidth: 0, flex: 1 }, children: [
|
|
6864
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: user.name }),
|
|
6865
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "fd-body-sm fd-muted fd-table-trunc", children: user.email })
|
|
6848
6866
|
] })
|
|
6849
6867
|
] }),
|
|
6850
|
-
showRoles && session.roles.length ? /* @__PURE__ */ (0,
|
|
6851
|
-
/* @__PURE__ */ (0,
|
|
6852
|
-
visibleAdmin.length ? /* @__PURE__ */ (0,
|
|
6853
|
-
/* @__PURE__ */ (0,
|
|
6854
|
-
visibleAdmin.map((l) => /* @__PURE__ */ (0,
|
|
6868
|
+
showRoles && session.roles.length ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "fd-row", style: { gap: 6, padding: "10px 14px", flexWrap: "wrap", borderBottom: "1px solid var(--border)" }, children: session.roles.map((r) => /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)) }) : null,
|
|
6869
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "fd-acct-group", children: links.map((l) => /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Item, { item: l, onPick: pick }, l.id)) }),
|
|
6870
|
+
visibleAdmin.length ? /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
|
|
6871
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "fd-overline fd-muted", style: { padding: "8px 14px 4px", display: "block" }, children: "Administration" }),
|
|
6872
|
+
visibleAdmin.map((l) => /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Item, { item: l, onPick: pick }, l.id))
|
|
6855
6873
|
] }) : null,
|
|
6856
|
-
allowUserSwitch ? /* @__PURE__ */ (0,
|
|
6857
|
-
/* @__PURE__ */ (0,
|
|
6858
|
-
/* @__PURE__ */ (0,
|
|
6859
|
-
/* @__PURE__ */ (0,
|
|
6860
|
-
/* @__PURE__ */ (0,
|
|
6874
|
+
allowUserSwitch ? /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
|
|
6875
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("button", { type: "button", role: "menuitem", className: "fd-acct-item", onClick: () => setSwitching((s) => !s), children: [
|
|
6876
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("i", { className: "ph ph-user-switch", "aria-hidden": "true" }),
|
|
6877
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { style: { flex: 1 }, children: "View as another member" }),
|
|
6878
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("i", { className: "ph ph-caret-" + (switching ? "up" : "down"), "aria-hidden": "true", style: { fontSize: 11 } })
|
|
6861
6879
|
] }),
|
|
6862
|
-
switching ? /* @__PURE__ */ (0,
|
|
6880
|
+
switching ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "fd-stack", style: { gap: 0, maxHeight: 208, overflowY: "auto" }, children: session.allUsers.filter((u) => u.status === "active").map((u) => /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
|
|
6863
6881
|
"button",
|
|
6864
6882
|
{
|
|
6865
6883
|
type: "button",
|
|
@@ -6871,34 +6889,34 @@ function AccountMenu({
|
|
|
6871
6889
|
setSwitching(false);
|
|
6872
6890
|
},
|
|
6873
6891
|
children: [
|
|
6874
|
-
/* @__PURE__ */ (0,
|
|
6875
|
-
/* @__PURE__ */ (0,
|
|
6876
|
-
/* @__PURE__ */ (0,
|
|
6877
|
-
/* @__PURE__ */ (0,
|
|
6892
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Avatar, { name: u.name, size: "sm" }),
|
|
6893
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "fd-stack", style: { gap: 0, flex: 1, minWidth: 0, alignItems: "flex-start" }, children: [
|
|
6894
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { style: { fontWeight: u.id === user.id ? 700 : 500 }, children: u.name }),
|
|
6895
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "fd-muted", style: { fontSize: 11.5 }, children: u.roles.join(", ") })
|
|
6878
6896
|
] }),
|
|
6879
|
-
u.id === user.id ? /* @__PURE__ */ (0,
|
|
6897
|
+
u.id === user.id ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("i", { className: "ph ph-check", "aria-hidden": "true", style: { color: "var(--ok-text)" } }) : null
|
|
6880
6898
|
]
|
|
6881
6899
|
},
|
|
6882
6900
|
u.id
|
|
6883
6901
|
)) }) : null
|
|
6884
6902
|
] }) : null,
|
|
6885
|
-
/* @__PURE__ */ (0,
|
|
6886
|
-
/* @__PURE__ */ (0,
|
|
6887
|
-
/* @__PURE__ */ (0,
|
|
6903
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("button", { type: "button", role: "menuitem", className: "fd-acct-item", "data-danger": "true", onClick: signOut, children: [
|
|
6904
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("i", { className: "ph ph-sign-out", "aria-hidden": "true" }),
|
|
6905
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { style: { flex: 1 }, children: "Sign out" })
|
|
6888
6906
|
] }) })
|
|
6889
6907
|
] }) })
|
|
6890
6908
|
] });
|
|
6891
6909
|
}
|
|
6892
6910
|
|
|
6893
6911
|
// src/components/platform/ApiSpecBrowser.tsx
|
|
6894
|
-
var
|
|
6895
|
-
var
|
|
6912
|
+
var React30 = __toESM(require("react"), 1);
|
|
6913
|
+
var import_jsx_runtime59 = require("react/jsx-runtime");
|
|
6896
6914
|
var METHOD_TONE = { GET: "success", POST: "info", PATCH: "warning", PUT: "warning", DELETE: "danger" };
|
|
6897
6915
|
function Json({ obj }) {
|
|
6898
|
-
return /* @__PURE__ */ (0,
|
|
6916
|
+
return /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
|
|
6899
6917
|
}
|
|
6900
6918
|
function Endpoint({ s, onRequest }) {
|
|
6901
|
-
const [tried, setTried] =
|
|
6919
|
+
const [tried, setTried] = React30.useState(null);
|
|
6902
6920
|
const run = async () => {
|
|
6903
6921
|
setTried("busy");
|
|
6904
6922
|
const t0 = (window.performance || Date).now();
|
|
@@ -6909,50 +6927,50 @@ function Endpoint({ s, onRequest }) {
|
|
|
6909
6927
|
setTried({ ms: Math.round((window.performance || Date).now() - t0), error: String(e && e.message || e) });
|
|
6910
6928
|
}
|
|
6911
6929
|
};
|
|
6912
|
-
return /* @__PURE__ */ (0,
|
|
6913
|
-
/* @__PURE__ */ (0,
|
|
6914
|
-
/* @__PURE__ */ (0,
|
|
6915
|
-
/* @__PURE__ */ (0,
|
|
6916
|
-
s.isList ? /* @__PURE__ */ (0,
|
|
6917
|
-
/* @__PURE__ */ (0,
|
|
6918
|
-
/* @__PURE__ */ (0,
|
|
6930
|
+
return /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Card, { elevation: "flat", padded: false, children: /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-stack", style: { gap: 0 }, children: [
|
|
6931
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "14px 18px", flexWrap: "wrap" }, children: [
|
|
6932
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Badge, { tone: METHOD_TONE[s.method] || "neutral", children: s.method }),
|
|
6933
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("code", { className: "fd-mono", style: { fontSize: 12.5, fontWeight: 600, color: "var(--text)", wordBreak: "break-all" }, children: s.path }),
|
|
6934
|
+
s.isList ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Badge, { tone: "neutral", icon: "rows", children: "Paged list" }) : null,
|
|
6935
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { style: { flex: 1 } }),
|
|
6936
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-body-sm fd-muted fd-mono", children: [
|
|
6919
6937
|
s.latency[0],
|
|
6920
6938
|
"\u2013",
|
|
6921
6939
|
s.latency[1],
|
|
6922
6940
|
"ms"
|
|
6923
6941
|
] }),
|
|
6924
|
-
/* @__PURE__ */ (0,
|
|
6942
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Button, { size: "sm", variant: "secondary", icon: "play", loading: tried === "busy", onClick: run, children: "Try it" })
|
|
6925
6943
|
] }),
|
|
6926
|
-
/* @__PURE__ */ (0,
|
|
6927
|
-
/* @__PURE__ */ (0,
|
|
6928
|
-
/* @__PURE__ */ (0,
|
|
6929
|
-
/* @__PURE__ */ (0,
|
|
6930
|
-
s.usedBy && s.usedBy.length ? /* @__PURE__ */ (0,
|
|
6944
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-stack", style: { gap: 14, padding: "0 18px 16px" }, children: [
|
|
6945
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
6946
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: s.title }),
|
|
6947
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: s.purpose }),
|
|
6948
|
+
s.usedBy && s.usedBy.length ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: s.usedBy.map((u) => /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Tag, { children: u }, u)) }) : null
|
|
6931
6949
|
] }),
|
|
6932
|
-
/* @__PURE__ */ (0,
|
|
6933
|
-
s.request ? /* @__PURE__ */ (0,
|
|
6934
|
-
/* @__PURE__ */ (0,
|
|
6935
|
-
/* @__PURE__ */ (0,
|
|
6950
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(280px,1fr))", gap: 12, alignItems: "start" }, children: [
|
|
6951
|
+
s.request ? /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
6952
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-overline fd-muted", children: "Request body" }),
|
|
6953
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Json, { obj: s.request })
|
|
6936
6954
|
] }) : null,
|
|
6937
|
-
s.query ? /* @__PURE__ */ (0,
|
|
6938
|
-
/* @__PURE__ */ (0,
|
|
6939
|
-
/* @__PURE__ */ (0,
|
|
6955
|
+
s.query ? /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
6956
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-overline fd-muted", children: "Query" }),
|
|
6957
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Json, { obj: s.query })
|
|
6940
6958
|
] }) : null,
|
|
6941
|
-
/* @__PURE__ */ (0,
|
|
6942
|
-
/* @__PURE__ */ (0,
|
|
6943
|
-
/* @__PURE__ */ (0,
|
|
6959
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
6960
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-overline fd-muted", children: "Response 200" }),
|
|
6961
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Json, { obj: s.response })
|
|
6944
6962
|
] })
|
|
6945
6963
|
] }),
|
|
6946
|
-
s.notes ? /* @__PURE__ */ (0,
|
|
6947
|
-
tried && tried !== "busy" ? /* @__PURE__ */ (0,
|
|
6948
|
-
/* @__PURE__ */ (0,
|
|
6949
|
-
/* @__PURE__ */ (0,
|
|
6950
|
-
/* @__PURE__ */ (0,
|
|
6964
|
+
s.notes ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Flag, { tone: "info", statement: "Implementation note", cost: s.notes, actions: null }) : null,
|
|
6965
|
+
tried && tried !== "busy" ? /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-stack", style: { gap: 6 }, children: [
|
|
6966
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
|
|
6967
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-overline fd-muted", children: "Simulated response" }),
|
|
6968
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(Badge, { tone: tried.error ? "danger" : "success", icon: "timer", children: [
|
|
6951
6969
|
tried.ms,
|
|
6952
6970
|
"ms"
|
|
6953
6971
|
] })
|
|
6954
6972
|
] }),
|
|
6955
|
-
/* @__PURE__ */ (0,
|
|
6973
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Json, { obj: tried.error ? { error: tried.error } : tried.data })
|
|
6956
6974
|
] }) : null
|
|
6957
6975
|
] })
|
|
6958
6976
|
] }) });
|
|
@@ -6971,58 +6989,58 @@ function ApiSpecBrowser({
|
|
|
6971
6989
|
className = "",
|
|
6972
6990
|
...rest
|
|
6973
6991
|
}) {
|
|
6974
|
-
const [q, setQ] =
|
|
6975
|
-
const [method, setMethod] =
|
|
6976
|
-
const [mod, setMod] =
|
|
6977
|
-
const [listOnly, setListOnly] =
|
|
6992
|
+
const [q, setQ] = React30.useState("");
|
|
6993
|
+
const [method, setMethod] = React30.useState(null);
|
|
6994
|
+
const [mod, setMod] = React30.useState(null);
|
|
6995
|
+
const [listOnly, setListOnly] = React30.useState(false);
|
|
6978
6996
|
const activeModule = modules && modules.find((m) => m.id === mod);
|
|
6979
6997
|
const hits = spec.filter((s) => (!method || s.method === method) && (!listOnly || s.isList) && (!activeModule || activeModule.endpoints.indexOf(s.id) >= 0) && (!q || (s.path + " " + s.title + " " + s.purpose + " " + (s.usedBy || []).join(" ")).toLowerCase().includes(q.toLowerCase())));
|
|
6980
6998
|
const effGroups = groups && groups.length ? groups : [["All endpoints", spec.map((s) => s.id)]];
|
|
6981
6999
|
const methods = [...new Set(spec.map((s) => s.method))];
|
|
6982
7000
|
const listCount = spec.filter((s) => s.isList).length;
|
|
6983
|
-
return /* @__PURE__ */ (0,
|
|
6984
|
-
/* @__PURE__ */ (0,
|
|
6985
|
-
kicker ? /* @__PURE__ */ (0,
|
|
6986
|
-
/* @__PURE__ */ (0,
|
|
6987
|
-
lede ? /* @__PURE__ */ (0,
|
|
7001
|
+
return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 1100 }, ...rest, children: [
|
|
7002
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
7003
|
+
kicker ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-overline fd-muted", children: kicker }) : null,
|
|
7004
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
|
|
7005
|
+
lede ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede }) : null
|
|
6988
7006
|
] }),
|
|
6989
|
-
modules && modules.length ? /* @__PURE__ */ (0,
|
|
6990
|
-
/* @__PURE__ */ (0,
|
|
6991
|
-
/* @__PURE__ */ (0,
|
|
6992
|
-
/* @__PURE__ */ (0,
|
|
7007
|
+
modules && modules.length ? /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-stack", style: { gap: 8 }, children: [
|
|
7008
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-overline fd-muted", children: "Filter by screen \u2014 every endpoint that screen depends on" }),
|
|
7009
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
|
|
7010
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(Tag, { icon: "stack", selected: !mod, onClick: () => setMod(null), children: [
|
|
6993
7011
|
"All screens ",
|
|
6994
|
-
/* @__PURE__ */ (0,
|
|
7012
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-mono", children: spec.length })
|
|
6995
7013
|
] }),
|
|
6996
|
-
modules.map((m) => /* @__PURE__ */ (0,
|
|
7014
|
+
modules.map((m) => /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(Tag, { icon: m.icon, selected: mod === m.id, onClick: () => setMod(mod === m.id ? null : m.id), children: [
|
|
6997
7015
|
m.label,
|
|
6998
7016
|
" ",
|
|
6999
|
-
/* @__PURE__ */ (0,
|
|
7017
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-mono", children: m.endpoints.length })
|
|
7000
7018
|
] }, m.id))
|
|
7001
7019
|
] }),
|
|
7002
|
-
activeModule ? /* @__PURE__ */ (0,
|
|
7020
|
+
activeModule ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
7003
7021
|
Flag,
|
|
7004
7022
|
{
|
|
7005
7023
|
tone: "info",
|
|
7006
7024
|
statement: activeModule.label + " calls " + activeModule.endpoints.length + " endpoints.",
|
|
7007
7025
|
cost: "Integration checklist for this screen: " + activeModule.endpoints.join(", ") + ". Wire these and the screen is done.",
|
|
7008
|
-
actions: /* @__PURE__ */ (0,
|
|
7026
|
+
actions: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Button, { size: "sm", variant: "ghost", icon: "x", onClick: () => setMod(null), children: "Show all screens" })
|
|
7009
7027
|
}
|
|
7010
7028
|
) : null
|
|
7011
7029
|
] }) : null,
|
|
7012
|
-
sourceNote ? /* @__PURE__ */ (0,
|
|
7013
|
-
/* @__PURE__ */ (0,
|
|
7014
|
-
/* @__PURE__ */ (0,
|
|
7015
|
-
methods.map((m) => /* @__PURE__ */ (0,
|
|
7030
|
+
sourceNote ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Flag, { tone: "info", statement: "Design-first: this page is the spec.", cost: sourceNote, actions: null }) : null,
|
|
7031
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
|
|
7032
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Input, { icon: "magnifying-glass", placeholder: "Find an endpoint, screen, or behavior", value: q, onChange: (e) => setQ(e.target.value), style: { width: 300 } }),
|
|
7033
|
+
methods.map((m) => /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(Tag, { selected: method === m, onClick: () => setMethod(method === m ? null : m), children: [
|
|
7016
7034
|
m,
|
|
7017
7035
|
" ",
|
|
7018
|
-
/* @__PURE__ */ (0,
|
|
7036
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-mono", children: spec.filter((s) => s.method === m).length })
|
|
7019
7037
|
] }, m)),
|
|
7020
|
-
listCount ? /* @__PURE__ */ (0,
|
|
7038
|
+
listCount ? /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(Tag, { icon: "rows", selected: listOnly, onClick: () => setListOnly(!listOnly), children: [
|
|
7021
7039
|
"Paged lists ",
|
|
7022
|
-
/* @__PURE__ */ (0,
|
|
7040
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-mono", children: listCount })
|
|
7023
7041
|
] }) : null,
|
|
7024
|
-
/* @__PURE__ */ (0,
|
|
7025
|
-
/* @__PURE__ */ (0,
|
|
7042
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { style: { flex: 1 } }),
|
|
7043
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
|
|
7026
7044
|
hits.length,
|
|
7027
7045
|
" of ",
|
|
7028
7046
|
spec.length,
|
|
@@ -7030,31 +7048,31 @@ function ApiSpecBrowser({
|
|
|
7030
7048
|
listCount ? " \xB7 " + listCount + " paged" : ""
|
|
7031
7049
|
] })
|
|
7032
7050
|
] }),
|
|
7033
|
-
hits.length === 0 ? /* @__PURE__ */ (0,
|
|
7051
|
+
hits.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Card, { elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No endpoint matches those filters." }) }) : effGroups.map(([g, ids]) => {
|
|
7034
7052
|
const items = hits.filter((s) => ids.indexOf(s.id) >= 0);
|
|
7035
7053
|
if (!items.length) return null;
|
|
7036
|
-
return /* @__PURE__ */ (0,
|
|
7037
|
-
/* @__PURE__ */ (0,
|
|
7038
|
-
items.map((s) => /* @__PURE__ */ (0,
|
|
7054
|
+
return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-stack", style: { gap: 12 }, children: [
|
|
7055
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-label-lg", children: g }),
|
|
7056
|
+
items.map((s) => /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Endpoint, { s, onRequest }, s.id))
|
|
7039
7057
|
] }, g);
|
|
7040
7058
|
}),
|
|
7041
|
-
conventions && conventions.length ? /* @__PURE__ */ (0,
|
|
7042
|
-
/* @__PURE__ */ (0,
|
|
7043
|
-
/* @__PURE__ */ (0,
|
|
7059
|
+
conventions && conventions.length ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Card, { title: "Cross-cutting conventions", elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "fd-stack", style: { gap: 10 }, children: conventions.map(([k, v]) => /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-row", style: { gap: 12, alignItems: "flex-start" }, children: [
|
|
7060
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-overline fd-muted", style: { width: 110, flex: "none", paddingTop: 2 }, children: k }),
|
|
7061
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: v })
|
|
7044
7062
|
] }, k)) }) }) : null,
|
|
7045
|
-
openQuestions && openQuestions.length ? /* @__PURE__ */ (0,
|
|
7046
|
-
/* @__PURE__ */ (0,
|
|
7047
|
-
/* @__PURE__ */ (0,
|
|
7048
|
-
/* @__PURE__ */ (0,
|
|
7049
|
-
/* @__PURE__ */ (0,
|
|
7063
|
+
openQuestions && openQuestions.length ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Collapsible, { icon: "list-checks", title: "Open questions before implementation", subtitle: openQuestions.length + " unresolved", children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "fd-stack", style: { gap: 8 }, children: openQuestions.map(([id, question, why]) => /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start", padding: "8px 0", borderTop: "1px solid var(--border)" }, children: [
|
|
7064
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(Badge, { tone: "danger", children: id }),
|
|
7065
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "fd-stack", style: { gap: 2, flex: 1 }, children: [
|
|
7066
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: question }),
|
|
7067
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "fd-body-sm fd-muted", children: why })
|
|
7050
7068
|
] })
|
|
7051
7069
|
] }, id)) }) }) : null
|
|
7052
7070
|
] });
|
|
7053
7071
|
}
|
|
7054
7072
|
|
|
7055
7073
|
// src/components/platform/ProfilePage.tsx
|
|
7056
|
-
var
|
|
7057
|
-
var
|
|
7074
|
+
var React31 = __toESM(require("react"), 1);
|
|
7075
|
+
var import_jsx_runtime60 = require("react/jsx-runtime");
|
|
7058
7076
|
var TIMEZONES = ["America/New_York", "America/Chicago", "America/Denver", "America/Los_Angeles", "America/Anchorage", "Pacific/Honolulu", "Europe/London", "Europe/Berlin"];
|
|
7059
7077
|
var NOTIFY = [
|
|
7060
7078
|
{ key: "planShared", label: "A plan is shared with me", detail: "Someone sends you a plan or a client link." },
|
|
@@ -7066,7 +7084,7 @@ var NOTIFY = [
|
|
|
7066
7084
|
function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSessions = true, className = "", ...rest }) {
|
|
7067
7085
|
const session = SessionKit.useSession();
|
|
7068
7086
|
const user = userProp || session.user;
|
|
7069
|
-
const [draft, setDraft] =
|
|
7087
|
+
const [draft, setDraft] = React31.useState(() => ({
|
|
7070
7088
|
name: user.name || "",
|
|
7071
7089
|
title: user.title || "",
|
|
7072
7090
|
email: user.email || "",
|
|
@@ -7075,8 +7093,8 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
7075
7093
|
bio: user.bio || "",
|
|
7076
7094
|
notify: user.notify || { planShared: true, planChanged: true, goalMissed: true, flagChanged: false, weekly: true }
|
|
7077
7095
|
}));
|
|
7078
|
-
const [saving, setSaving] =
|
|
7079
|
-
const [saved, setSaved] =
|
|
7096
|
+
const [saving, setSaving] = React31.useState(false);
|
|
7097
|
+
const [saved, setSaved] = React31.useState(false);
|
|
7080
7098
|
const set = (k, v) => {
|
|
7081
7099
|
setDraft((d) => Object.assign({}, d, { [k]: v }));
|
|
7082
7100
|
setSaved(false);
|
|
@@ -7098,43 +7116,43 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
7098
7116
|
{ id: "s2", device: "iPhone 15 \xB7 Safari", where: "Denver, CO", when: "2 hours ago" },
|
|
7099
7117
|
{ id: "s3", device: "Windows \xB7 Edge", where: "Chicago, IL", when: "Aug 12" }
|
|
7100
7118
|
];
|
|
7101
|
-
return /* @__PURE__ */ (0,
|
|
7102
|
-
/* @__PURE__ */ (0,
|
|
7103
|
-
/* @__PURE__ */ (0,
|
|
7104
|
-
/* @__PURE__ */ (0,
|
|
7105
|
-
/* @__PURE__ */ (0,
|
|
7119
|
+
return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 860 }, ...rest, children: [
|
|
7120
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
7121
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { className: "fd-overline fd-muted", children: "Account" }),
|
|
7122
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: "Your profile" }),
|
|
7123
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: "How you appear to colleagues and clients across every flytedesk app, and what we send you." })
|
|
7106
7124
|
] }),
|
|
7107
|
-
/* @__PURE__ */ (0,
|
|
7108
|
-
/* @__PURE__ */ (0,
|
|
7109
|
-
/* @__PURE__ */ (0,
|
|
7110
|
-
/* @__PURE__ */ (0,
|
|
7111
|
-
/* @__PURE__ */ (0,
|
|
7125
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)(Card, { elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "fd-row", style: { gap: 16, flexWrap: "wrap", alignItems: "flex-start" }, children: [
|
|
7126
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)(Avatar, { name: draft.name || user.name, size: "lg" }),
|
|
7127
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "fd-stack", style: { gap: 4, flex: 1, minWidth: 200 }, children: [
|
|
7128
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { className: "fd-h3", style: { margin: 0 }, children: draft.name || user.name }),
|
|
7129
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
|
|
7112
7130
|
draft.title || "No title set",
|
|
7113
7131
|
" \xB7 ",
|
|
7114
7132
|
user.team || "No team"
|
|
7115
7133
|
] }),
|
|
7116
|
-
/* @__PURE__ */ (0,
|
|
7117
|
-
session.roles.map((r) => /* @__PURE__ */ (0,
|
|
7118
|
-
user.sso ? /* @__PURE__ */ (0,
|
|
7134
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 4 }, children: [
|
|
7135
|
+
session.roles.map((r) => /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)),
|
|
7136
|
+
user.sso ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(Badge, { tone: "info", icon: "shield-check", children: "SSO" }) : null
|
|
7119
7137
|
] })
|
|
7120
7138
|
] }),
|
|
7121
|
-
/* @__PURE__ */ (0,
|
|
7139
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)(Button, { variant: "secondary", size: "sm", icon: "image", children: "Change photo" })
|
|
7122
7140
|
] }) }),
|
|
7123
|
-
/* @__PURE__ */ (0,
|
|
7141
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
|
|
7124
7142
|
Card,
|
|
7125
7143
|
{
|
|
7126
|
-
title: /* @__PURE__ */ (0,
|
|
7127
|
-
/* @__PURE__ */ (0,
|
|
7128
|
-
/* @__PURE__ */ (0,
|
|
7144
|
+
title: /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { className: "fd-stack", style: { gap: 2 }, children: [
|
|
7145
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { children: "Identity" }),
|
|
7146
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "Name and title appear on plans you share" })
|
|
7129
7147
|
] }),
|
|
7130
7148
|
elevation: "flat",
|
|
7131
|
-
children: /* @__PURE__ */ (0,
|
|
7132
|
-
/* @__PURE__ */ (0,
|
|
7133
|
-
/* @__PURE__ */ (0,
|
|
7134
|
-
/* @__PURE__ */ (0,
|
|
7149
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "fd-stack", style: { gap: 14 }, children: [
|
|
7150
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: [
|
|
7151
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)(Input, { label: "Full name", value: draft.name, onChange: (e) => set("name", e.target.value) }),
|
|
7152
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)(Input, { label: "Job title", value: draft.title, onChange: (e) => set("title", e.target.value), placeholder: "e.g. Senior media planner" })
|
|
7135
7153
|
] }),
|
|
7136
|
-
/* @__PURE__ */ (0,
|
|
7137
|
-
/* @__PURE__ */ (0,
|
|
7154
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: [
|
|
7155
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
|
|
7138
7156
|
Input,
|
|
7139
7157
|
{
|
|
7140
7158
|
label: "Work email",
|
|
@@ -7144,9 +7162,9 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
7144
7162
|
help: user.sso ? "Managed by your identity provider \u2014 change it there." : "Contact an administrator to change this."
|
|
7145
7163
|
}
|
|
7146
7164
|
),
|
|
7147
|
-
/* @__PURE__ */ (0,
|
|
7165
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)(Input, { label: "Phone", value: draft.phone, onChange: (e) => set("phone", e.target.value), placeholder: "Optional" })
|
|
7148
7166
|
] }),
|
|
7149
|
-
/* @__PURE__ */ (0,
|
|
7167
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
|
|
7150
7168
|
Textarea,
|
|
7151
7169
|
{
|
|
7152
7170
|
label: "Short bio",
|
|
@@ -7160,8 +7178,8 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
7160
7178
|
] })
|
|
7161
7179
|
}
|
|
7162
7180
|
),
|
|
7163
|
-
/* @__PURE__ */ (0,
|
|
7164
|
-
/* @__PURE__ */ (0,
|
|
7181
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)(Card, { title: "Working preferences", elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: [
|
|
7182
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
|
|
7165
7183
|
Select,
|
|
7166
7184
|
{
|
|
7167
7185
|
label: "Time zone",
|
|
@@ -7171,28 +7189,28 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
7171
7189
|
help: "Flight dates and schedules render in this zone."
|
|
7172
7190
|
}
|
|
7173
7191
|
),
|
|
7174
|
-
/* @__PURE__ */ (0,
|
|
7192
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)(Select, { label: "Start of week", options: ["Monday", "Sunday"], placeholder: "Monday" })
|
|
7175
7193
|
] }) }),
|
|
7176
|
-
/* @__PURE__ */ (0,
|
|
7194
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
|
|
7177
7195
|
Card,
|
|
7178
7196
|
{
|
|
7179
|
-
title: /* @__PURE__ */ (0,
|
|
7180
|
-
/* @__PURE__ */ (0,
|
|
7181
|
-
/* @__PURE__ */ (0,
|
|
7197
|
+
title: /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { className: "fd-stack", style: { gap: 2 }, children: [
|
|
7198
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { children: "Notifications" }),
|
|
7199
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "Email only for now \u2014 in-app notifications are on the roadmap" })
|
|
7182
7200
|
] }),
|
|
7183
7201
|
elevation: "flat",
|
|
7184
|
-
children: /* @__PURE__ */ (0,
|
|
7202
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "fd-stack", style: { gap: 14 }, children: NOTIFY.map((n) => /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(Switch, { checked: !!draft.notify[n.key], onChange: () => setNotify(n.key), label: n.label, description: n.detail }, n.key)) })
|
|
7185
7203
|
}
|
|
7186
7204
|
),
|
|
7187
|
-
/* @__PURE__ */ (0,
|
|
7205
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(
|
|
7188
7206
|
Card,
|
|
7189
7207
|
{
|
|
7190
|
-
title: /* @__PURE__ */ (0,
|
|
7191
|
-
/* @__PURE__ */ (0,
|
|
7192
|
-
/* @__PURE__ */ (0,
|
|
7208
|
+
title: /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { className: "fd-stack", style: { gap: 2 }, children: [
|
|
7209
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { children: "Access" }),
|
|
7210
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "What your roles grant you" })
|
|
7193
7211
|
] }),
|
|
7194
7212
|
elevation: "flat",
|
|
7195
|
-
action: /* @__PURE__ */ (0,
|
|
7213
|
+
action: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
|
|
7196
7214
|
Button,
|
|
7197
7215
|
{
|
|
7198
7216
|
size: "sm",
|
|
@@ -7203,39 +7221,39 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
7203
7221
|
}
|
|
7204
7222
|
),
|
|
7205
7223
|
children: [
|
|
7206
|
-
/* @__PURE__ */ (0,
|
|
7207
|
-
/* @__PURE__ */ (0,
|
|
7208
|
-
/* @__PURE__ */ (0,
|
|
7224
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "fd-stack", style: { gap: 0 }, children: [
|
|
7225
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)(CardRow, { label: "Roles", children: session.roles.map((r) => r.name).join(", ") || "None" }),
|
|
7226
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(CardRow, { label: "Permissions", children: [
|
|
7209
7227
|
session.permissions.length,
|
|
7210
7228
|
" granted"
|
|
7211
7229
|
] }),
|
|
7212
|
-
/* @__PURE__ */ (0,
|
|
7230
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)(CardRow, { label: "Member since", children: user.joined || "\u2014" })
|
|
7213
7231
|
] }),
|
|
7214
|
-
/* @__PURE__ */ (0,
|
|
7232
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("p", { className: "fd-body-sm fd-muted", style: { margin: "12px 0 0" }, children: "You cannot change your own roles \u2014 that is the point of them. An administrator manages roles from Admin \u2192 Users." })
|
|
7215
7233
|
]
|
|
7216
7234
|
}
|
|
7217
7235
|
),
|
|
7218
|
-
showSessions ? /* @__PURE__ */ (0,
|
|
7236
|
+
showSessions ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
|
|
7219
7237
|
Card,
|
|
7220
7238
|
{
|
|
7221
7239
|
title: "Signed-in devices",
|
|
7222
7240
|
elevation: "flat",
|
|
7223
|
-
action: /* @__PURE__ */ (0,
|
|
7224
|
-
children: /* @__PURE__ */ (0,
|
|
7225
|
-
/* @__PURE__ */ (0,
|
|
7226
|
-
/* @__PURE__ */ (0,
|
|
7227
|
-
/* @__PURE__ */ (0,
|
|
7228
|
-
/* @__PURE__ */ (0,
|
|
7241
|
+
action: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(Button, { size: "sm", variant: "ghost", icon: "sign-out", children: "Sign out everywhere" }),
|
|
7242
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "fd-stack", style: { gap: 0 }, children: liveSessions.map((s) => /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "fd-row", style: { gap: 12, padding: "10px 0", borderTop: "1px solid var(--border)", flexWrap: "wrap" }, children: [
|
|
7243
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("i", { className: "ph ph-device-mobile", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
|
|
7244
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { className: "fd-stack", style: { gap: 1, flex: 1, minWidth: 160 }, children: [
|
|
7245
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: s.device }),
|
|
7246
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
|
|
7229
7247
|
s.where,
|
|
7230
7248
|
" \xB7 ",
|
|
7231
7249
|
s.when
|
|
7232
7250
|
] })
|
|
7233
7251
|
] }),
|
|
7234
|
-
s.current ? /* @__PURE__ */ (0,
|
|
7252
|
+
s.current ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(Badge, { tone: "success", dot: true, children: "This device" }) : /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(Button, { size: "sm", variant: "ghost", children: "Revoke" })
|
|
7235
7253
|
] }, s.id)) })
|
|
7236
7254
|
}
|
|
7237
7255
|
) : null,
|
|
7238
|
-
/* @__PURE__ */ (0,
|
|
7256
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "fd-row", style: {
|
|
7239
7257
|
gap: 10,
|
|
7240
7258
|
flexWrap: "wrap",
|
|
7241
7259
|
position: "sticky",
|
|
@@ -7246,8 +7264,8 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
7246
7264
|
border: "1px solid var(--border)",
|
|
7247
7265
|
boxShadow: "0 -4px 16px rgba(11,13,17,.06)"
|
|
7248
7266
|
}, children: [
|
|
7249
|
-
/* @__PURE__ */ (0,
|
|
7250
|
-
/* @__PURE__ */ (0,
|
|
7267
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 600, flex: 1 }, children: saved ? "Saved." : dirty ? "Unsaved changes" : "No pending changes" }),
|
|
7268
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
|
|
7251
7269
|
Button,
|
|
7252
7270
|
{
|
|
7253
7271
|
size: "sm",
|
|
@@ -7260,16 +7278,16 @@ function ProfilePage({ user: userProp, onSave, onNavigate, sessions, showSession
|
|
|
7260
7278
|
children: "Discard"
|
|
7261
7279
|
}
|
|
7262
7280
|
),
|
|
7263
|
-
/* @__PURE__ */ (0,
|
|
7281
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)(Button, { size: "sm", icon: "check", disabled: !dirty, loading: saving, onClick: save, children: "Save changes" })
|
|
7264
7282
|
] })
|
|
7265
7283
|
] });
|
|
7266
7284
|
}
|
|
7267
7285
|
|
|
7268
7286
|
// src/components/platform/RoadmapTimeline.tsx
|
|
7269
|
-
var
|
|
7287
|
+
var React33 = __toESM(require("react"), 1);
|
|
7270
7288
|
|
|
7271
7289
|
// src/kits/runtime.ts
|
|
7272
|
-
var
|
|
7290
|
+
var React32 = __toESM(require("react"), 1);
|
|
7273
7291
|
var WIRED_ENDPOINTS = [
|
|
7274
7292
|
// Nothing yet. Every id below would come from a real service:
|
|
7275
7293
|
// "plan.get", "placements.list", …
|
|
@@ -7440,8 +7458,8 @@ var RuntimeKit = {
|
|
|
7440
7458
|
};
|
|
7441
7459
|
RuntimeKit.declare(FEATURE_NEEDS);
|
|
7442
7460
|
function useRuntimeMode() {
|
|
7443
|
-
const [m, setM] =
|
|
7444
|
-
|
|
7461
|
+
const [m, setM] = React32.useState(RuntimeKit.getMode());
|
|
7462
|
+
React32.useEffect(() => RuntimeKit.subscribe(setM), []);
|
|
7445
7463
|
return m;
|
|
7446
7464
|
}
|
|
7447
7465
|
function useFeatureStatus(key) {
|
|
@@ -7460,7 +7478,7 @@ var UseRuntimeMode = useRuntimeMode;
|
|
|
7460
7478
|
var UseFeatureStatus = useFeatureStatus;
|
|
7461
7479
|
|
|
7462
7480
|
// src/components/platform/RoadmapTimeline.tsx
|
|
7463
|
-
var
|
|
7481
|
+
var import_jsx_runtime61 = require("react/jsx-runtime");
|
|
7464
7482
|
var STATUS = {
|
|
7465
7483
|
shipped: { tone: "success", icon: "check-circle", label: "Wired" },
|
|
7466
7484
|
next: { tone: "warning", icon: "traffic-cone", label: "Not wired" },
|
|
@@ -7475,45 +7493,45 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
|
|
|
7475
7493
|
const s = STATUS[item.status] || STATUS.planned;
|
|
7476
7494
|
const deps = (item.dependsOn || []).map((k) => byKey[k]).filter(Boolean);
|
|
7477
7495
|
const blocking = deps.filter((d) => !d.implemented);
|
|
7478
|
-
return /* @__PURE__ */ (0,
|
|
7479
|
-
/* @__PURE__ */ (0,
|
|
7480
|
-
/* @__PURE__ */ (0,
|
|
7481
|
-
/* @__PURE__ */ (0,
|
|
7482
|
-
/* @__PURE__ */ (0,
|
|
7496
|
+
return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(Card, { elevation: "flat", children: /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
7497
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
|
|
7498
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { className: "fd-body", style: { fontWeight: 700, flex: 1, minWidth: 140 }, children: item.label }),
|
|
7499
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)(Badge, { tone: "neutral", icon: PROJECT_ICON[item.project] || "squares-four", children: item.project }),
|
|
7500
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)(Badge, { tone: s.tone, icon: s.icon, children: s.label })
|
|
7483
7501
|
] }),
|
|
7484
|
-
/* @__PURE__ */ (0,
|
|
7485
|
-
item.backend ? /* @__PURE__ */ (0,
|
|
7486
|
-
/* @__PURE__ */ (0,
|
|
7487
|
-
/* @__PURE__ */ (0,
|
|
7502
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: item.description }),
|
|
7503
|
+
item.backend ? /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start" }, children: [
|
|
7504
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { className: "fd-overline fd-muted", style: { width: 62, flex: "none", paddingTop: 2 }, children: "Backend" }),
|
|
7505
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { className: "fd-body-sm", style: { flex: 1, textWrap: "pretty" }, children: item.backend })
|
|
7488
7506
|
] }) : null,
|
|
7489
|
-
/* @__PURE__ */ (0,
|
|
7490
|
-
item.effort ? /* @__PURE__ */ (0,
|
|
7491
|
-
/* @__PURE__ */ (0,
|
|
7507
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
|
|
7508
|
+
item.effort ? /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
|
|
7509
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("i", { className: "ph ph-hourglass-medium" }),
|
|
7492
7510
|
" ",
|
|
7493
7511
|
item.effort
|
|
7494
7512
|
] }) : null,
|
|
7495
|
-
/* @__PURE__ */ (0,
|
|
7496
|
-
/* @__PURE__ */ (0,
|
|
7513
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("span", { className: "fd-body-sm fd-muted", children: [
|
|
7514
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("i", { className: "ph ph-user" }),
|
|
7497
7515
|
" ",
|
|
7498
7516
|
item.owner
|
|
7499
7517
|
] }),
|
|
7500
|
-
item.screen ? /* @__PURE__ */ (0,
|
|
7501
|
-
/* @__PURE__ */ (0,
|
|
7502
|
-
/* @__PURE__ */ (0,
|
|
7518
|
+
item.screen ? /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(Badge, { tone: "neutral", icon: "browser", children: "screen" }) : null,
|
|
7519
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { style: { flex: 1 } }),
|
|
7520
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
|
|
7503
7521
|
"button",
|
|
7504
7522
|
{
|
|
7505
7523
|
type: "button",
|
|
7506
7524
|
onClick: () => onOpenFlag && onOpenFlag(item.key),
|
|
7507
7525
|
style: { all: "unset", cursor: "pointer", display: "inline-flex", alignItems: "center", gap: 5 },
|
|
7508
|
-
children: /* @__PURE__ */ (0,
|
|
7526
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("code", { className: "fd-mono", style: { fontSize: 11, color: "var(--brand)" }, children: item.key })
|
|
7509
7527
|
}
|
|
7510
7528
|
)
|
|
7511
7529
|
] }),
|
|
7512
|
-
deps.length ? /* @__PURE__ */ (0,
|
|
7513
|
-
/* @__PURE__ */ (0,
|
|
7514
|
-
deps.map((d) => /* @__PURE__ */ (0,
|
|
7530
|
+
deps.length ? /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 6, borderTop: "1px solid var(--border)" }, children: [
|
|
7531
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { className: "fd-overline fd-muted", style: { paddingTop: 3 }, children: "After" }),
|
|
7532
|
+
deps.map((d) => /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(Tag, { icon: d.implemented ? "check" : "clock", children: d.label }, d.key))
|
|
7515
7533
|
] }) : null,
|
|
7516
|
-
blocking.length && !item.implemented ? /* @__PURE__ */ (0,
|
|
7534
|
+
blocking.length && !item.implemented ? /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("span", { className: "fd-body-sm", style: { color: "var(--warn-text)" }, children: [
|
|
7517
7535
|
"Blocked until ",
|
|
7518
7536
|
blocking.map((d) => d.label).join(" and "),
|
|
7519
7537
|
" ",
|
|
@@ -7524,12 +7542,12 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
|
|
|
7524
7542
|
}
|
|
7525
7543
|
function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
7526
7544
|
const session = SessionKit.useSession();
|
|
7527
|
-
const [project, setProject] =
|
|
7528
|
-
const [q, setQ] =
|
|
7529
|
-
const scrollRef =
|
|
7530
|
-
const nowRef =
|
|
7531
|
-
const rm =
|
|
7532
|
-
const byKey =
|
|
7545
|
+
const [project, setProject] = React33.useState("");
|
|
7546
|
+
const [q, setQ] = React33.useState("");
|
|
7547
|
+
const scrollRef = React33.useRef(null);
|
|
7548
|
+
const nowRef = React33.useRef(null);
|
|
7549
|
+
const rm = React33.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
|
|
7550
|
+
const byKey = React33.useMemo(() => {
|
|
7533
7551
|
const m = {};
|
|
7534
7552
|
rm.items.forEach((i) => {
|
|
7535
7553
|
m[i.key] = i;
|
|
@@ -7538,7 +7556,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
7538
7556
|
}, [rm]);
|
|
7539
7557
|
const items = rm.items.filter((i) => (!project || i.project === project) && (!q || (i.label + " " + i.description + " " + (i.backend || "") + " " + i.key).toLowerCase().includes(q.toLowerCase())));
|
|
7540
7558
|
const projects = [...new Set(rm.items.map((i) => i.project))];
|
|
7541
|
-
|
|
7559
|
+
React33.useEffect(() => {
|
|
7542
7560
|
let raf1 = 0, raf2 = 0;
|
|
7543
7561
|
const place = () => {
|
|
7544
7562
|
const box = scrollRef.current, mark = nowRef.current;
|
|
@@ -7566,23 +7584,23 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
7566
7584
|
}, 0);
|
|
7567
7585
|
const nextPhase = items.find((i) => !i.implemented);
|
|
7568
7586
|
let lastPhase = null;
|
|
7569
|
-
return /* @__PURE__ */ (0,
|
|
7570
|
-
/* @__PURE__ */ (0,
|
|
7571
|
-
/* @__PURE__ */ (0,
|
|
7572
|
-
/* @__PURE__ */ (0,
|
|
7573
|
-
/* @__PURE__ */ (0,
|
|
7587
|
+
return /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: "fd-stack", style: { gap: 16, maxWidth: 1e3 }, children: [
|
|
7588
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: "fd-stack", style: { gap: 10 }, children: [
|
|
7589
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { className: "fd-overline fd-muted", children: "Architecture" }),
|
|
7590
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
|
|
7591
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede || "Every screen and feature in these tools is already designed and working against a simulated backend. This is the plan for connecting them to the real one \u2014 so the only work described here is server work." })
|
|
7574
7592
|
] }),
|
|
7575
|
-
/* @__PURE__ */ (0,
|
|
7576
|
-
/* @__PURE__ */ (0,
|
|
7577
|
-
/* @__PURE__ */ (0,
|
|
7578
|
-
/* @__PURE__ */ (0,
|
|
7579
|
-
/* @__PURE__ */ (0,
|
|
7593
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: "fd-grid-stats is-thin", children: [
|
|
7594
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)(StatTile, { compact: true, label: "Wired", value: String(rm.shipped), sub: "of " + rm.items.length + " features" }),
|
|
7595
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)(StatTile, { compact: true, label: "Remaining", value: String(rm.remaining), sub: "backend work" }),
|
|
7596
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)(StatTile, { compact: true, label: "Est. effort", value: days ? days + " days" : "\u2014", sub: "sum of estimates, not calendar" }),
|
|
7597
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)(StatTile, { compact: true, label: "Up next", value: nextPhase ? "Phase " + nextPhase.phase : "\u2014", sub: nextPhase ? nextPhase.phaseName : "all wired" })
|
|
7580
7598
|
] }),
|
|
7581
|
-
/* @__PURE__ */ (0,
|
|
7582
|
-
/* @__PURE__ */ (0,
|
|
7583
|
-
/* @__PURE__ */ (0,
|
|
7584
|
-
/* @__PURE__ */ (0,
|
|
7585
|
-
/* @__PURE__ */ (0,
|
|
7599
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
|
|
7600
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)(Input, { icon: "magnifying-glass", placeholder: "Find a feature or a piece of backend work", value: q, onChange: (e) => setQ(e.target.value), style: { width: 300 } }),
|
|
7601
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)(Select, { placeholder: "All projects", value: project, onChange: (e) => setProject(e.target.value), options: projects, style: { width: 190 } }),
|
|
7602
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { style: { flex: 1 } }),
|
|
7603
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
|
|
7586
7604
|
Button,
|
|
7587
7605
|
{
|
|
7588
7606
|
size: "sm",
|
|
@@ -7596,7 +7614,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
7596
7614
|
}
|
|
7597
7615
|
)
|
|
7598
7616
|
] }),
|
|
7599
|
-
/* @__PURE__ */ (0,
|
|
7617
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
|
|
7600
7618
|
Flag,
|
|
7601
7619
|
{
|
|
7602
7620
|
tone: "info",
|
|
@@ -7605,60 +7623,60 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
|
|
|
7605
7623
|
actions: null
|
|
7606
7624
|
}
|
|
7607
7625
|
),
|
|
7608
|
-
/* @__PURE__ */ (0,
|
|
7609
|
-
/* @__PURE__ */ (0,
|
|
7626
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("div", { className: "fd-rm", children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("div", { className: "fd-rm-scroll", ref: scrollRef, children: /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: "fd-rm-track", children: [
|
|
7627
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { className: "fd-rm-spine", children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { className: "fd-rm-spine-done", style: { height: items.length ? 100 * shippedShown / items.length + "%" : "0%" } }) }),
|
|
7610
7628
|
items.map((item, n) => {
|
|
7611
7629
|
const showPhase = item.phase !== lastPhase;
|
|
7612
7630
|
lastPhase = item.phase;
|
|
7613
7631
|
const inPhase = items.filter((i) => i.phase === item.phase).length;
|
|
7614
7632
|
const isBoundary = n === firstPending;
|
|
7615
|
-
return /* @__PURE__ */ (0,
|
|
7616
|
-
showPhase ? /* @__PURE__ */ (0,
|
|
7617
|
-
/* @__PURE__ */ (0,
|
|
7618
|
-
/* @__PURE__ */ (0,
|
|
7619
|
-
item.phase === 0 ? null : /* @__PURE__ */ (0,
|
|
7633
|
+
return /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)(React33.Fragment, { children: [
|
|
7634
|
+
showPhase ? /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: "fd-rm-era", children: [
|
|
7635
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
|
|
7636
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
|
|
7637
|
+
item.phase === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("span", { className: "fd-mono", style: { opacity: 0.7, fontWeight: 400 }, children: [
|
|
7620
7638
|
fmtDate(item.phaseStart),
|
|
7621
7639
|
" \u2013 ",
|
|
7622
7640
|
fmtDate(item.date)
|
|
7623
7641
|
] }),
|
|
7624
|
-
/* @__PURE__ */ (0,
|
|
7642
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("span", { style: { opacity: 0.7, fontWeight: 400 }, children: [
|
|
7625
7643
|
"\xB7 ",
|
|
7626
7644
|
inPhase,
|
|
7627
7645
|
" feature",
|
|
7628
7646
|
inPhase === 1 ? "" : "s"
|
|
7629
7647
|
] })
|
|
7630
7648
|
] }),
|
|
7631
|
-
item.phaseWhy ? /* @__PURE__ */ (0,
|
|
7649
|
+
item.phaseWhy ? /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("p", { className: "fd-rm-era-why", children: item.phaseWhy }) : null
|
|
7632
7650
|
] }) : null,
|
|
7633
|
-
isBoundary ? /* @__PURE__ */ (0,
|
|
7634
|
-
/* @__PURE__ */ (0,
|
|
7651
|
+
isBoundary ? /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("div", { className: "fd-rm-now", ref: nowRef, children: /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("span", { className: "fd-rm-now-pill", children: [
|
|
7652
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("i", { className: "ph ph-map-pin" }),
|
|
7635
7653
|
" You are here \u2014 everything above is wired"
|
|
7636
7654
|
] }) }) : null,
|
|
7637
|
-
/* @__PURE__ */ (0,
|
|
7638
|
-
/* @__PURE__ */ (0,
|
|
7639
|
-
/* @__PURE__ */ (0,
|
|
7655
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: "fd-rm-row", children: [
|
|
7656
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { className: "fd-rm-dot " + (item.implemented ? "is-shipped" : item.status === "next" ? "is-next" : "") }),
|
|
7657
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: "fd-rm-date", children: [
|
|
7640
7658
|
fmtDate(item.date),
|
|
7641
|
-
/* @__PURE__ */ (0,
|
|
7642
|
-
/* @__PURE__ */ (0,
|
|
7659
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("br", {}),
|
|
7660
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { style: { opacity: 0.75 }, children: item.implemented ? "shipped" : "phase " + item.phase })
|
|
7643
7661
|
] }),
|
|
7644
|
-
/* @__PURE__ */ (0,
|
|
7662
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)(RoadmapCard, { item, byKey, onOpenFlag })
|
|
7645
7663
|
] })
|
|
7646
7664
|
] }, item.key);
|
|
7647
7665
|
}),
|
|
7648
|
-
!items.length ? /* @__PURE__ */ (0,
|
|
7666
|
+
!items.length ? /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("p", { className: "fd-body-sm fd-muted", children: "Nothing matches that filter." }) : null
|
|
7649
7667
|
] }) }) }),
|
|
7650
|
-
/* @__PURE__ */ (0,
|
|
7668
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: [
|
|
7651
7669
|
"Derived from the feature-flag registry \u2014 each entry's status is its flag's ",
|
|
7652
|
-
/* @__PURE__ */ (0,
|
|
7670
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("code", { className: "fd-mono", children: "implemented" }),
|
|
7653
7671
|
" field, so this page cannot drift from what the apps actually do."
|
|
7654
7672
|
] })
|
|
7655
7673
|
] });
|
|
7656
7674
|
}
|
|
7657
7675
|
|
|
7658
7676
|
// src/components/platform/ComingSoon.tsx
|
|
7659
|
-
var
|
|
7677
|
+
var React34 = __toESM(require("react"), 1);
|
|
7660
7678
|
var import_react_dom8 = require("react-dom");
|
|
7661
|
-
var
|
|
7679
|
+
var import_jsx_runtime62 = require("react/jsx-runtime");
|
|
7662
7680
|
var BYPASS_STORE = "fd.soon.bypass.v1";
|
|
7663
7681
|
function readBypassed() {
|
|
7664
7682
|
try {
|
|
@@ -7674,8 +7692,8 @@ function writeBypassed(list) {
|
|
|
7674
7692
|
}
|
|
7675
7693
|
}
|
|
7676
7694
|
function useBypass(key) {
|
|
7677
|
-
const [on, setOn] =
|
|
7678
|
-
|
|
7695
|
+
const [on, setOn] = React34.useState(() => !!key && readBypassed().indexOf(key) >= 0);
|
|
7696
|
+
React34.useEffect(() => {
|
|
7679
7697
|
setOn(!!key && readBypassed().indexOf(key) >= 0);
|
|
7680
7698
|
}, [key]);
|
|
7681
7699
|
const set = (next) => {
|
|
@@ -7688,43 +7706,43 @@ function useBypass(key) {
|
|
|
7688
7706
|
return [on, set];
|
|
7689
7707
|
}
|
|
7690
7708
|
function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass }) {
|
|
7691
|
-
return /* @__PURE__ */ (0,
|
|
7692
|
-
/* @__PURE__ */ (0,
|
|
7693
|
-
/* @__PURE__ */ (0,
|
|
7709
|
+
return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)(import_jsx_runtime62.Fragment, { children: [
|
|
7710
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-soon-badge", children: [
|
|
7711
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
|
|
7694
7712
|
label
|
|
7695
7713
|
] }),
|
|
7696
|
-
detail ? /* @__PURE__ */ (0,
|
|
7697
|
-
backend ? /* @__PURE__ */ (0,
|
|
7698
|
-
/* @__PURE__ */ (0,
|
|
7714
|
+
detail ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-soon-detail", children: detail }) : null,
|
|
7715
|
+
backend ? /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-soon-backend", children: [
|
|
7716
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-overline", children: "Needs" }),
|
|
7699
7717
|
" ",
|
|
7700
7718
|
backend
|
|
7701
7719
|
] }) : null,
|
|
7702
|
-
eta || effort || onRoadmap ? /* @__PURE__ */ (0,
|
|
7703
|
-
eta ? /* @__PURE__ */ (0,
|
|
7704
|
-
/* @__PURE__ */ (0,
|
|
7720
|
+
eta || effort || onRoadmap ? /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-soon-meta", children: [
|
|
7721
|
+
eta ? /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { children: [
|
|
7722
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }),
|
|
7705
7723
|
" ",
|
|
7706
7724
|
eta
|
|
7707
7725
|
] }) : null,
|
|
7708
|
-
effort ? /* @__PURE__ */ (0,
|
|
7709
|
-
/* @__PURE__ */ (0,
|
|
7726
|
+
effort ? /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { children: [
|
|
7727
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-hourglass-medium", "aria-hidden": "true" }),
|
|
7710
7728
|
" ",
|
|
7711
7729
|
effort
|
|
7712
7730
|
] }) : null,
|
|
7713
|
-
onRoadmap ? /* @__PURE__ */ (0,
|
|
7731
|
+
onRoadmap ? /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
|
|
7714
7732
|
"See the roadmap ",
|
|
7715
|
-
/* @__PURE__ */ (0,
|
|
7733
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
|
|
7716
7734
|
] }) : null
|
|
7717
7735
|
] }) : null,
|
|
7718
|
-
allowed ? /* @__PURE__ */ (0,
|
|
7719
|
-
/* @__PURE__ */ (0,
|
|
7736
|
+
allowed ? /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("button", { type: "button", className: "fd-soon-view", onClick: onBypass, children: [
|
|
7737
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-eye", "aria-hidden": "true" }),
|
|
7720
7738
|
" View and use it anyway"
|
|
7721
7739
|
] }) : null
|
|
7722
7740
|
] });
|
|
7723
7741
|
}
|
|
7724
7742
|
function useHoverCard(open) {
|
|
7725
|
-
const anchor =
|
|
7726
|
-
const [pos, setPos] =
|
|
7727
|
-
|
|
7743
|
+
const anchor = React34.useRef(null);
|
|
7744
|
+
const [pos, setPos] = React34.useState(null);
|
|
7745
|
+
React34.useLayoutEffect(() => {
|
|
7728
7746
|
if (!open || !anchor.current) {
|
|
7729
7747
|
setPos(null);
|
|
7730
7748
|
return;
|
|
@@ -7776,9 +7794,9 @@ function ComingSoon({
|
|
|
7776
7794
|
const tip = [label, detail, backend ? "Needs " + backend : null, eta ? "ETA " + eta : null, effort].filter(Boolean).join(" \xB7 ");
|
|
7777
7795
|
if (inline) {
|
|
7778
7796
|
if (allowed && bypassed) {
|
|
7779
|
-
return /* @__PURE__ */ (0,
|
|
7797
|
+
return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: ["fd-soon-inline-on", className].filter(Boolean).join(" "), ...rest, children: [
|
|
7780
7798
|
children,
|
|
7781
|
-
/* @__PURE__ */ (0,
|
|
7799
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
|
|
7782
7800
|
"button",
|
|
7783
7801
|
{
|
|
7784
7802
|
type: "button",
|
|
@@ -7786,12 +7804,12 @@ function ComingSoon({
|
|
|
7786
7804
|
title: "Unwired \u2014 writes go to the simulated backend. " + tip + " Click to re-blur.",
|
|
7787
7805
|
onClick: () => setBypassed(false),
|
|
7788
7806
|
"aria-label": "Re-blur this unwired feature",
|
|
7789
|
-
children: /* @__PURE__ */ (0,
|
|
7807
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
|
|
7790
7808
|
}
|
|
7791
7809
|
)
|
|
7792
7810
|
] });
|
|
7793
7811
|
}
|
|
7794
|
-
return /* @__PURE__ */ (0,
|
|
7812
|
+
return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
|
|
7795
7813
|
InlineSoon,
|
|
7796
7814
|
{
|
|
7797
7815
|
label,
|
|
@@ -7811,20 +7829,20 @@ function ComingSoon({
|
|
|
7811
7829
|
);
|
|
7812
7830
|
}
|
|
7813
7831
|
if (allowed && bypassed) {
|
|
7814
|
-
return /* @__PURE__ */ (0,
|
|
7815
|
-
/* @__PURE__ */ (0,
|
|
7816
|
-
/* @__PURE__ */ (0,
|
|
7817
|
-
/* @__PURE__ */ (0,
|
|
7832
|
+
return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, ...rest, children: [
|
|
7833
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "fd-soon-bar", role: "status", children: [
|
|
7834
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-soon-badge", children: [
|
|
7835
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
|
|
7818
7836
|
"Unwired feature \u2014 you are using it anyway"
|
|
7819
7837
|
] }),
|
|
7820
|
-
/* @__PURE__ */ (0,
|
|
7821
|
-
/* @__PURE__ */ (0,
|
|
7822
|
-
onRoadmap ? /* @__PURE__ */ (0,
|
|
7838
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-soon-bar-detail", children: "Every action here writes to the simulated backend, so nothing you do persists beyond this session." }),
|
|
7839
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-soon-bar-actions", children: [
|
|
7840
|
+
onRoadmap ? /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
|
|
7823
7841
|
"Roadmap ",
|
|
7824
|
-
/* @__PURE__ */ (0,
|
|
7842
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
|
|
7825
7843
|
] }) : null,
|
|
7826
|
-
/* @__PURE__ */ (0,
|
|
7827
|
-
/* @__PURE__ */ (0,
|
|
7844
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: () => setBypassed(false), children: [
|
|
7845
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-eye-slash", "aria-hidden": "true" }),
|
|
7828
7846
|
" Re-blur"
|
|
7829
7847
|
] })
|
|
7830
7848
|
] })
|
|
@@ -7832,10 +7850,10 @@ function ComingSoon({
|
|
|
7832
7850
|
children
|
|
7833
7851
|
] });
|
|
7834
7852
|
}
|
|
7835
|
-
return /* @__PURE__ */ (0,
|
|
7836
|
-
/* @__PURE__ */ (0,
|
|
7837
|
-
/* @__PURE__ */ (0,
|
|
7838
|
-
/* @__PURE__ */ (0,
|
|
7853
|
+
return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: ["fd-soon", className].filter(Boolean).join(" "), style: minHeight ? { minHeight } : void 0, ...rest, children: [
|
|
7854
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { className: "fd-soon-under", style: { filter: "blur(" + blur + "px) saturate(.62)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
|
|
7855
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { className: "fd-soon-veil" }),
|
|
7856
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { className: "fd-soon-note", role: "note", children: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
|
|
7839
7857
|
SoonCard,
|
|
7840
7858
|
{
|
|
7841
7859
|
label,
|
|
@@ -7851,9 +7869,9 @@ function ComingSoon({
|
|
|
7851
7869
|
] });
|
|
7852
7870
|
}
|
|
7853
7871
|
function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
|
|
7854
|
-
const [open, setOpen] =
|
|
7872
|
+
const [open, setOpen] = React34.useState(false);
|
|
7855
7873
|
const [anchor, pos] = useHoverCard(open);
|
|
7856
|
-
const close =
|
|
7874
|
+
const close = React34.useRef(null);
|
|
7857
7875
|
const show = () => {
|
|
7858
7876
|
if (close.current) {
|
|
7859
7877
|
clearTimeout(close.current);
|
|
@@ -7869,10 +7887,10 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
7869
7887
|
setOpen(false);
|
|
7870
7888
|
}, 140);
|
|
7871
7889
|
};
|
|
7872
|
-
|
|
7890
|
+
React34.useEffect(() => () => {
|
|
7873
7891
|
if (close.current) clearTimeout(close.current);
|
|
7874
7892
|
}, []);
|
|
7875
|
-
return /* @__PURE__ */ (0,
|
|
7893
|
+
return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)(
|
|
7876
7894
|
"span",
|
|
7877
7895
|
{
|
|
7878
7896
|
ref: anchor,
|
|
@@ -7883,8 +7901,8 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
7883
7901
|
onBlur: hide,
|
|
7884
7902
|
...rest,
|
|
7885
7903
|
children: [
|
|
7886
|
-
/* @__PURE__ */ (0,
|
|
7887
|
-
/* @__PURE__ */ (0,
|
|
7904
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-soon-under", style: { filter: "blur(" + Math.min(blur, 1.1) + "px) saturate(.66)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
|
|
7905
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
|
|
7888
7906
|
"button",
|
|
7889
7907
|
{
|
|
7890
7908
|
type: "button",
|
|
@@ -7895,11 +7913,11 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
7895
7913
|
onFocus: show,
|
|
7896
7914
|
onBlur: hide,
|
|
7897
7915
|
onClick: () => open ? setOpen(false) : show(),
|
|
7898
|
-
children: /* @__PURE__ */ (0,
|
|
7916
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
|
|
7899
7917
|
}
|
|
7900
7918
|
),
|
|
7901
7919
|
open && pos ? (0, import_react_dom8.createPortal)(
|
|
7902
|
-
/* @__PURE__ */ (0,
|
|
7920
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
|
|
7903
7921
|
"div",
|
|
7904
7922
|
{
|
|
7905
7923
|
className: "fd-soon-note fd-soon-hovercard",
|
|
@@ -7907,7 +7925,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
|
|
|
7907
7925
|
style: { position: "fixed", left: pos.left, top: pos.top, bottom: pos.bottom, width: pos.width },
|
|
7908
7926
|
onMouseEnter: show,
|
|
7909
7927
|
onMouseLeave: hide,
|
|
7910
|
-
children: /* @__PURE__ */ (0,
|
|
7928
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
|
|
7911
7929
|
SoonCard,
|
|
7912
7930
|
{
|
|
7913
7931
|
label,
|
|
@@ -7937,10 +7955,10 @@ function formatEta(iso2) {
|
|
|
7937
7955
|
var FormatEta = formatEta;
|
|
7938
7956
|
|
|
7939
7957
|
// src/components/platform/Gate.tsx
|
|
7940
|
-
var
|
|
7958
|
+
var import_jsx_runtime63 = require("react/jsx-runtime");
|
|
7941
7959
|
function PermissionDenied({ permission, title, detail, compact: compact3 = false, className = "", ...rest }) {
|
|
7942
7960
|
const need = Array.isArray(permission) ? permission : [permission].filter(Boolean);
|
|
7943
|
-
return /* @__PURE__ */ (0,
|
|
7961
|
+
return /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(
|
|
7944
7962
|
"div",
|
|
7945
7963
|
{
|
|
7946
7964
|
className: ["fd-stack", className].filter(Boolean).join(" "),
|
|
@@ -7956,14 +7974,14 @@ function PermissionDenied({ permission, title, detail, compact: compact3 = false
|
|
|
7956
7974
|
},
|
|
7957
7975
|
...rest,
|
|
7958
7976
|
children: [
|
|
7959
|
-
/* @__PURE__ */ (0,
|
|
7960
|
-
/* @__PURE__ */ (0,
|
|
7961
|
-
/* @__PURE__ */ (0,
|
|
7977
|
+
/* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
|
|
7978
|
+
/* @__PURE__ */ (0, import_jsx_runtime63.jsx)("i", { className: "ph ph-lock-simple", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
|
|
7979
|
+
/* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: title || "You do not have access to this" })
|
|
7962
7980
|
] }),
|
|
7963
|
-
/* @__PURE__ */ (0,
|
|
7964
|
-
need.length ? /* @__PURE__ */ (0,
|
|
7965
|
-
/* @__PURE__ */ (0,
|
|
7966
|
-
need.map((p) => /* @__PURE__ */ (0,
|
|
7981
|
+
/* @__PURE__ */ (0, import_jsx_runtime63.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: detail || "Your roles do not grant this. An administrator can change that from Admin \u2192 Users." }),
|
|
7982
|
+
need.length ? /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: [
|
|
7983
|
+
/* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "fd-overline fd-muted", children: "Requires" }),
|
|
7984
|
+
need.map((p) => /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("code", { className: "fd-mono", style: {
|
|
7967
7985
|
fontSize: 11.5,
|
|
7968
7986
|
padding: "2px 7px",
|
|
7969
7987
|
borderRadius: 5,
|
|
@@ -7984,7 +8002,7 @@ function Gate({ perm, anyOf, role, silent = false, fallback, compact: compact3 =
|
|
|
7984
8002
|
if (ok) return children;
|
|
7985
8003
|
if (fallback !== void 0) return fallback;
|
|
7986
8004
|
if (silent) return null;
|
|
7987
|
-
return /* @__PURE__ */ (0,
|
|
8005
|
+
return /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(PermissionDenied, { permission: perm || anyOf, compact: compact3 });
|
|
7988
8006
|
}
|
|
7989
8007
|
function FeatureGate({
|
|
7990
8008
|
flag,
|
|
@@ -8005,7 +8023,7 @@ function FeatureGate({
|
|
|
8005
8023
|
if (!preview) return fallback;
|
|
8006
8024
|
const f = SessionKit.findFlag(flag) || {};
|
|
8007
8025
|
const missing = rt.missing || [];
|
|
8008
|
-
return /* @__PURE__ */ (0,
|
|
8026
|
+
return /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
|
|
8009
8027
|
ComingSoon,
|
|
8010
8028
|
{
|
|
8011
8029
|
label: label || (variant === "inline" ? f.label || "Not wired yet" : "Designed \u2014 backend not wired yet"),
|
|
@@ -8026,25 +8044,25 @@ function FeatureGate({
|
|
|
8026
8044
|
function PermissionHint({ perm, children }) {
|
|
8027
8045
|
SessionKit.useSession();
|
|
8028
8046
|
if (SessionKit.can(perm)) return children;
|
|
8029
|
-
return /* @__PURE__ */ (0,
|
|
8047
|
+
return /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
|
|
8030
8048
|
"span",
|
|
8031
8049
|
{
|
|
8032
8050
|
title: "Requires " + (Array.isArray(perm) ? perm.join(", ") : perm),
|
|
8033
8051
|
style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" },
|
|
8034
8052
|
"aria-disabled": "true",
|
|
8035
|
-
children: /* @__PURE__ */ (0,
|
|
8053
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { style: { pointerEvents: "none" }, children })
|
|
8036
8054
|
}
|
|
8037
8055
|
);
|
|
8038
8056
|
}
|
|
8039
8057
|
|
|
8040
8058
|
// src/components/platform/ModeSwitch.tsx
|
|
8041
|
-
var
|
|
8042
|
-
var
|
|
8059
|
+
var React35 = __toESM(require("react"), 1);
|
|
8060
|
+
var import_jsx_runtime64 = require("react/jsx-runtime");
|
|
8043
8061
|
function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog, onOpenSpec, summary }) {
|
|
8044
8062
|
const mode2 = useRuntimeMode();
|
|
8045
|
-
const [open, setOpen] =
|
|
8046
|
-
const ref =
|
|
8047
|
-
|
|
8063
|
+
const [open, setOpen] = React35.useState(false);
|
|
8064
|
+
const ref = React35.useRef(null);
|
|
8065
|
+
React35.useEffect(() => {
|
|
8048
8066
|
if (!open) return;
|
|
8049
8067
|
const away = (e) => {
|
|
8050
8068
|
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
@@ -8066,8 +8084,8 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
8066
8084
|
RuntimeKit.setMode(next);
|
|
8067
8085
|
setOpen(false);
|
|
8068
8086
|
};
|
|
8069
|
-
return /* @__PURE__ */ (0,
|
|
8070
|
-
/* @__PURE__ */ (0,
|
|
8087
|
+
return /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("span", { style: { position: "relative", display: "inline-flex" }, ref, children: [
|
|
8088
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsxs)(
|
|
8071
8089
|
"button",
|
|
8072
8090
|
{
|
|
8073
8091
|
type: "button",
|
|
@@ -8077,29 +8095,29 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
8077
8095
|
title: test ? "Test mode \u2014 every response is simulated. Click to inspect requests or return to live mode." : "Live mode \u2014 incomplete features are shown under construction. Click for test mode.",
|
|
8078
8096
|
className: "fd-mode-btn" + (test ? " is-test" : "") + (open ? " is-open" : ""),
|
|
8079
8097
|
children: [
|
|
8080
|
-
/* @__PURE__ */ (0,
|
|
8081
|
-
test && requestCount ? /* @__PURE__ */ (0,
|
|
8098
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), style: { fontSize: 17 } }),
|
|
8099
|
+
test && requestCount ? /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "fd-mono fd-mode-count", children: requestCount > 99 ? "99+" : requestCount }, requestCount) : null
|
|
8082
8100
|
]
|
|
8083
8101
|
}
|
|
8084
8102
|
),
|
|
8085
|
-
open ? /* @__PURE__ */ (0,
|
|
8086
|
-
/* @__PURE__ */ (0,
|
|
8087
|
-
/* @__PURE__ */ (0,
|
|
8088
|
-
/* @__PURE__ */ (0,
|
|
8103
|
+
open ? /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("span", { className: "fd-view-enter fd-mode-pop", children: [
|
|
8104
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("span", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
|
|
8105
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("span", { className: "fd-badge " + (test ? "fd-badge-warning" : "fd-badge-neutral"), children: [
|
|
8106
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), "aria-hidden": "true" }),
|
|
8089
8107
|
test ? "Test mode" : "Live mode"
|
|
8090
8108
|
] }),
|
|
8091
|
-
test ? /* @__PURE__ */ (0,
|
|
8109
|
+
test ? /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("span", { className: "fd-body-sm fd-muted fd-mono", children: [
|
|
8092
8110
|
requestCount,
|
|
8093
8111
|
" simulated request",
|
|
8094
8112
|
requestCount === 1 ? "" : "s"
|
|
8095
8113
|
] }) : null,
|
|
8096
|
-
/* @__PURE__ */ (0,
|
|
8097
|
-
test && onClearLog ? /* @__PURE__ */ (0,
|
|
8114
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { style: { flex: 1 } }),
|
|
8115
|
+
test && onClearLog ? /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("button", { type: "button", className: "fd-soon-link", onClick: onClearLog, children: "Clear" }) : null
|
|
8098
8116
|
] }),
|
|
8099
|
-
/* @__PURE__ */ (0,
|
|
8100
|
-
/* @__PURE__ */ (0,
|
|
8101
|
-
/* @__PURE__ */ (0,
|
|
8102
|
-
/* @__PURE__ */ (0,
|
|
8117
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("span", { style: { display: "block", padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
|
|
8118
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "fd-body-sm fd-secondary", style: { display: "block", textWrap: "pretty" }, children: test ? "Every feature is usable and nothing is obstructed, but no response comes from a real service \u2014 nothing you do here persists. Use this to review and demo the design." : "This is what a user would see today. " + s.incomplete + " of " + s.total + " features depend on backend work that is not wired yet, so they render under construction." }),
|
|
8119
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("span", { className: "fd-row", style: { gap: 8, marginTop: 10, flexWrap: "wrap" }, children: [
|
|
8120
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("span", { className: "fd-body-sm fd-muted fd-mono", children: [
|
|
8103
8121
|
s.endpointsWired,
|
|
8104
8122
|
" endpoint",
|
|
8105
8123
|
s.endpointsWired === 1 ? "" : "s",
|
|
@@ -8109,58 +8127,58 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
|
|
|
8109
8127
|
s.total,
|
|
8110
8128
|
" features complete"
|
|
8111
8129
|
] }),
|
|
8112
|
-
onOpenSpec ? /* @__PURE__ */ (0,
|
|
8113
|
-
/* @__PURE__ */ (0,
|
|
8114
|
-
/* @__PURE__ */ (0,
|
|
8130
|
+
onOpenSpec ? /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)(import_jsx_runtime64.Fragment, { children: [
|
|
8131
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { style: { flex: 1 } }),
|
|
8132
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: () => {
|
|
8115
8133
|
setOpen(false);
|
|
8116
8134
|
onOpenSpec();
|
|
8117
8135
|
}, children: [
|
|
8118
8136
|
"API spec ",
|
|
8119
|
-
/* @__PURE__ */ (0,
|
|
8137
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
|
|
8120
8138
|
] })
|
|
8121
8139
|
] }) : null
|
|
8122
8140
|
] })
|
|
8123
8141
|
] }),
|
|
8124
|
-
/* @__PURE__ */ (0,
|
|
8125
|
-
/* @__PURE__ */ (0,
|
|
8126
|
-
/* @__PURE__ */ (0,
|
|
8127
|
-
/* @__PURE__ */ (0,
|
|
8128
|
-
/* @__PURE__ */ (0,
|
|
8129
|
-
/* @__PURE__ */ (0,
|
|
8142
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("span", { className: "fd-mode-choice", children: [
|
|
8143
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("button", { type: "button", className: "fd-mode-opt" + (!test ? " is-on" : ""), onClick: () => go("live"), children: [
|
|
8144
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
|
|
8145
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("span", { className: "fd-mode-opt-text", children: [
|
|
8146
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "fd-mode-opt-title", children: "Live mode" }),
|
|
8147
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "fd-mode-opt-desc", children: "Incomplete features under construction" })
|
|
8130
8148
|
] }),
|
|
8131
|
-
!test ? /* @__PURE__ */ (0,
|
|
8149
|
+
!test ? /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
|
|
8132
8150
|
] }),
|
|
8133
|
-
/* @__PURE__ */ (0,
|
|
8134
|
-
/* @__PURE__ */ (0,
|
|
8135
|
-
/* @__PURE__ */ (0,
|
|
8136
|
-
/* @__PURE__ */ (0,
|
|
8137
|
-
/* @__PURE__ */ (0,
|
|
8151
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("button", { type: "button", className: "fd-mode-opt" + (test ? " is-on" : ""), onClick: () => go("test"), children: [
|
|
8152
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)("i", { className: "ph ph-flask", "aria-hidden": "true" }),
|
|
8153
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("span", { className: "fd-mode-opt-text", children: [
|
|
8154
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "fd-mode-opt-title", children: "Test mode" }),
|
|
8155
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "fd-mode-opt-desc", children: "Everything usable, all data simulated" })
|
|
8138
8156
|
] }),
|
|
8139
|
-
test ? /* @__PURE__ */ (0,
|
|
8157
|
+
test ? /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
|
|
8140
8158
|
] })
|
|
8141
8159
|
] }),
|
|
8142
|
-
test && renderLog ? /* @__PURE__ */ (0,
|
|
8160
|
+
test && renderLog ? /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { style: { display: "block", maxHeight: 340, overflowY: "auto", borderTop: "1px solid var(--border)" }, children: renderLog() }) : null
|
|
8143
8161
|
] }) : null
|
|
8144
8162
|
] });
|
|
8145
8163
|
}
|
|
8146
8164
|
function TestModeBar({ onExit }) {
|
|
8147
8165
|
const mode2 = useRuntimeMode();
|
|
8148
8166
|
if (mode2 !== "test") return null;
|
|
8149
|
-
return /* @__PURE__ */ (0,
|
|
8150
|
-
/* @__PURE__ */ (0,
|
|
8151
|
-
/* @__PURE__ */ (0,
|
|
8167
|
+
return /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("div", { className: "fd-testbar", role: "status", children: [
|
|
8168
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("span", { className: "fd-badge fd-badge-warning", children: [
|
|
8169
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)("i", { className: "ph ph-flask", "aria-hidden": "true" }),
|
|
8152
8170
|
"Test mode"
|
|
8153
8171
|
] }),
|
|
8154
|
-
/* @__PURE__ */ (0,
|
|
8155
|
-
/* @__PURE__ */ (0,
|
|
8156
|
-
/* @__PURE__ */ (0,
|
|
8172
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "fd-testbar-detail", children: "Every feature is unlocked and every response is simulated \u2014 nothing here persists." }),
|
|
8173
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("button", { type: "button", className: "fd-soon-link", onClick: () => onExit ? onExit() : RuntimeKit.setMode("live"), children: [
|
|
8174
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
|
|
8157
8175
|
" Back to live mode"
|
|
8158
8176
|
] })
|
|
8159
8177
|
] });
|
|
8160
8178
|
}
|
|
8161
8179
|
|
|
8162
8180
|
// src/components/planner/ChannelMeta.tsx
|
|
8163
|
-
var
|
|
8181
|
+
var import_jsx_runtime65 = require("react/jsx-runtime");
|
|
8164
8182
|
var CHANNEL_WEIGHTS = {
|
|
8165
8183
|
"OOH": 50,
|
|
8166
8184
|
"DOOH": 50,
|
|
@@ -8213,9 +8231,9 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
|
|
|
8213
8231
|
const m = ChannelMeta(channel);
|
|
8214
8232
|
const wt = channelWeightOf(channel || "");
|
|
8215
8233
|
if (dot) {
|
|
8216
|
-
return /* @__PURE__ */ (0,
|
|
8234
|
+
return /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { className: ["fd-chan-dot", className].filter(Boolean).join(" "), title: m.name, style: { background: m.color }, ...rest });
|
|
8217
8235
|
}
|
|
8218
|
-
return /* @__PURE__ */ (0,
|
|
8236
|
+
return /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)(
|
|
8219
8237
|
"span",
|
|
8220
8238
|
{
|
|
8221
8239
|
className: ["fd-chan", size === "sm" ? "fd-chan-sm" : "", className].filter(Boolean).join(" "),
|
|
@@ -8223,16 +8241,16 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
|
|
|
8223
8241
|
style: { "--chan": m.color },
|
|
8224
8242
|
...rest,
|
|
8225
8243
|
children: [
|
|
8226
|
-
/* @__PURE__ */ (0,
|
|
8227
|
-
showLabel ? /* @__PURE__ */ (0,
|
|
8228
|
-
weight ? /* @__PURE__ */ (0,
|
|
8244
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsx)("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }),
|
|
8245
|
+
showLabel ? /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { className: "fd-chan-label", children: m.label }) : null,
|
|
8246
|
+
weight ? /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { className: "fd-chan-weight", children: wt || 0 }) : null
|
|
8229
8247
|
]
|
|
8230
8248
|
}
|
|
8231
8249
|
);
|
|
8232
8250
|
}
|
|
8233
8251
|
|
|
8234
8252
|
// src/components/planner/SaturationDistribution.tsx
|
|
8235
|
-
var
|
|
8253
|
+
var import_jsx_runtime66 = require("react/jsx-runtime");
|
|
8236
8254
|
var BANDS2 = [
|
|
8237
8255
|
{ key: "weak", label: "Weak", n: 1, range: "< 50" },
|
|
8238
8256
|
{ key: "adequate", label: "Adequate", n: 2, range: "50\u2013100" },
|
|
@@ -8243,18 +8261,18 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
8243
8261
|
const grouped = BANDS2.map((b) => ({ ...b, items: campuses.filter((c) => c.band === b.key) }));
|
|
8244
8262
|
const tallest = Math.max(1, ...grouped.map((g) => g.items.length));
|
|
8245
8263
|
const floor = BANDS2.find((b) => b.key === floorBand) || BANDS2[0];
|
|
8246
|
-
return /* @__PURE__ */ (0,
|
|
8247
|
-
/* @__PURE__ */ (0,
|
|
8264
|
+
return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
|
|
8265
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("div", { style: { display: "grid", gridTemplateColumns: "repeat(4,1fr)", gap: 12, alignItems: "end" }, children: grouped.map((g) => {
|
|
8248
8266
|
const mark = "var(--csi-" + g.n + "-mark)";
|
|
8249
8267
|
const active = selectedBand === g.key;
|
|
8250
|
-
return /* @__PURE__ */ (0,
|
|
8268
|
+
return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(
|
|
8251
8269
|
"button",
|
|
8252
8270
|
{
|
|
8253
8271
|
type: "button",
|
|
8254
8272
|
onClick: onSelectBand ? () => onSelectBand(active ? null : g.key) : void 0,
|
|
8255
8273
|
style: { display: "flex", flexDirection: "column", justifyContent: "flex-end", gap: 10, padding: 12, border: "1px solid " + (active ? "var(--border-strong)" : "var(--border)"), borderRadius: "var(--r-lg)", background: active ? "var(--surface-2)" : "var(--surface)", cursor: onSelectBand ? "pointer" : "default", textAlign: "left", minHeight: 190, transition: "background var(--dur-fast) var(--ease),border-color var(--dur-fast) var(--ease)" },
|
|
8256
8274
|
children: [
|
|
8257
|
-
/* @__PURE__ */ (0,
|
|
8275
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { style: { display: "flex", flexDirection: "column-reverse", gap: 4, minHeight: tallest * 24 }, children: loading ? Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "fd-skel", style: { height: 16, borderRadius: 4 } }, i)) : g.items.map((c) => /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
|
|
8258
8276
|
"span",
|
|
8259
8277
|
{
|
|
8260
8278
|
title: c.name + " \xB7 " + c.crp,
|
|
@@ -8263,13 +8281,13 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
8263
8281
|
},
|
|
8264
8282
|
c.name
|
|
8265
8283
|
)) }),
|
|
8266
|
-
/* @__PURE__ */ (0,
|
|
8267
|
-
/* @__PURE__ */ (0,
|
|
8268
|
-
/* @__PURE__ */ (0,
|
|
8284
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("span", { className: "fd-row", style: { gap: 8, alignItems: "baseline" }, children: [
|
|
8285
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "fd-num-hero", style: { fontSize: 30, color: g.items.length ? "var(--text)" : "var(--text-disabled)" }, children: loading ? "\u2013" : g.items.length }),
|
|
8286
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "fd-meter", style: { gap: 2, color: mark }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "fd-meter-seg" + (i <= g.n ? " is-on" : ""), style: { width: 4, height: 9 } }, i)) })
|
|
8269
8287
|
] }),
|
|
8270
|
-
/* @__PURE__ */ (0,
|
|
8271
|
-
/* @__PURE__ */ (0,
|
|
8272
|
-
/* @__PURE__ */ (0,
|
|
8288
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("span", { className: "fd-stack", style: { gap: 1 }, children: [
|
|
8289
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "fd-label-lg", children: g.label }),
|
|
8290
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("span", { className: "fd-body-sm fd-muted", style: { fontSize: 11.5 }, children: [
|
|
8273
8291
|
"CRP ",
|
|
8274
8292
|
g.range
|
|
8275
8293
|
] })
|
|
@@ -8279,10 +8297,10 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
8279
8297
|
g.key
|
|
8280
8298
|
);
|
|
8281
8299
|
}) }),
|
|
8282
|
-
floorBand ? /* @__PURE__ */ (0,
|
|
8283
|
-
/* @__PURE__ */ (0,
|
|
8284
|
-
/* @__PURE__ */ (0,
|
|
8285
|
-
/* @__PURE__ */ (0,
|
|
8300
|
+
floorBand ? /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderRadius: "var(--r-md)", background: "var(--surface-2)", border: "1px solid var(--border)", flexWrap: "wrap" }, children: [
|
|
8301
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "fd-meter", style: { gap: 2, color: "var(--csi-" + floor.n + "-mark)" }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "fd-meter-seg" + (i <= floor.n ? " is-on" : ""), style: { width: 5, height: 12 } }, i)) }),
|
|
8302
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("span", { className: "fd-body-sm fd-secondary", style: { flex: 1, minWidth: 240 }, children: [
|
|
8303
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("strong", { style: { color: "var(--text)" }, children: [
|
|
8286
8304
|
"Plan floor ",
|
|
8287
8305
|
floorScore
|
|
8288
8306
|
] }),
|
|
@@ -8293,21 +8311,21 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
|
|
|
8293
8311
|
}
|
|
8294
8312
|
|
|
8295
8313
|
// src/components/planner/MixGap.tsx
|
|
8296
|
-
var
|
|
8297
|
-
var
|
|
8314
|
+
var React36 = __toESM(require("react"), 1);
|
|
8315
|
+
var import_jsx_runtime67 = require("react/jsx-runtime");
|
|
8298
8316
|
function MixGap({ rows = [], loading = false, className = "" }) {
|
|
8299
8317
|
const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
|
|
8300
|
-
const [hover, setHover] =
|
|
8318
|
+
const [hover, setHover] = React36.useState(null);
|
|
8301
8319
|
const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
|
|
8302
8320
|
const TONE = { ok: "var(--ok-solid)", warn: "var(--warn-solid)", danger: "var(--danger-solid)" };
|
|
8303
|
-
return /* @__PURE__ */ (0,
|
|
8304
|
-
/* @__PURE__ */ (0,
|
|
8305
|
-
[["On target", TONE.ok], ["Close", TONE.warn], ["Short", TONE.danger]].map(([l, c]) => /* @__PURE__ */ (0,
|
|
8306
|
-
/* @__PURE__ */ (0,
|
|
8321
|
+
return /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 4 }, children: [
|
|
8322
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { className: "fd-row", style: { gap: 16, justifyContent: "flex-end", paddingBottom: 6, flexWrap: "wrap" }, children: [
|
|
8323
|
+
[["On target", TONE.ok], ["Close", TONE.warn], ["Short", TONE.danger]].map(([l, c]) => /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
|
|
8324
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { style: { width: 14, height: 9, borderRadius: 2, background: c } }),
|
|
8307
8325
|
l
|
|
8308
8326
|
] }, l)),
|
|
8309
|
-
/* @__PURE__ */ (0,
|
|
8310
|
-
/* @__PURE__ */ (0,
|
|
8327
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
|
|
8328
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { style: { width: 3, height: 14, background: "var(--n-500)" } }),
|
|
8311
8329
|
"Target"
|
|
8312
8330
|
] })
|
|
8313
8331
|
] }),
|
|
@@ -8315,7 +8333,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
8315
8333
|
const gap = r.realized - r.target;
|
|
8316
8334
|
const tone = toneOf(gap);
|
|
8317
8335
|
const tip = "Realized " + r.realized + "% vs " + r.target + "% target" + (gap < -1 ? " \xB7 " + Math.abs(gap).toFixed(0) + " pts short" : gap > 1 ? " \xB7 " + gap.toFixed(0) + " pts over" : " \xB7 on target") + (r.note ? " \u2014 " + r.note : "");
|
|
8318
|
-
return /* @__PURE__ */ (0,
|
|
8336
|
+
return /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)(
|
|
8319
8337
|
"div",
|
|
8320
8338
|
{
|
|
8321
8339
|
className: "fd-row",
|
|
@@ -8323,15 +8341,15 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
8323
8341
|
onMouseEnter: () => setHover(r.channel),
|
|
8324
8342
|
onMouseLeave: () => setHover(null),
|
|
8325
8343
|
children: [
|
|
8326
|
-
/* @__PURE__ */ (0,
|
|
8327
|
-
/* @__PURE__ */ (0,
|
|
8328
|
-
/* @__PURE__ */ (0,
|
|
8329
|
-
/* @__PURE__ */ (0,
|
|
8330
|
-
/* @__PURE__ */ (0,
|
|
8344
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { style: { width: 128, flex: "none" }, children: /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(ChannelTag, { channel: r.channel, size: "sm" }) }),
|
|
8345
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { style: { position: "relative", flex: 1, height: 22, minWidth: 120 }, children: loading ? /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { className: "fd-skel", style: { position: "absolute", inset: "5px 0", borderRadius: 3 } }) : /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)(import_jsx_runtime67.Fragment, { children: [
|
|
8346
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { style: { position: "absolute", left: 0, top: 5, height: 12, width: r.realized / max * 100 + "%", background: TONE[tone], borderRadius: "2px 3px 3px 2px", transition: "width var(--dur-slow) var(--ease), background var(--dur-base) var(--ease)" } }),
|
|
8347
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { style: { position: "absolute", left: r.target / max * 100 + "%", top: 0, width: 3, height: 22, background: "var(--n-500)", borderRadius: 1 } }),
|
|
8348
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("span", { className: "fd-num", style: { position: "absolute", right: Math.max(r.realized, r.target) / max > 0.82 ? 0 : "auto", left: Math.max(r.realized, r.target) / max > 0.82 ? "auto" : "calc(" + Math.max(r.realized, r.target) / max * 100 + "% + 10px)", top: 2, fontSize: 12, color: "var(--text-muted)", whiteSpace: "nowrap", background: Math.max(r.realized, r.target) / max > 0.82 ? "var(--surface)" : "none", paddingLeft: 3 }, children: [
|
|
8331
8349
|
r.realized,
|
|
8332
8350
|
"%"
|
|
8333
8351
|
] }),
|
|
8334
|
-
hover === r.channel ? /* @__PURE__ */ (0,
|
|
8352
|
+
hover === r.channel ? /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { className: "fd-tooltip", role: "tooltip", style: { position: "absolute", left: 0, right: "auto", bottom: 26, maxWidth: "min(340px, 100%)", whiteSpace: "normal", textAlign: "left", width: "max-content" }, children: tip }) : null
|
|
8335
8353
|
] }) })
|
|
8336
8354
|
]
|
|
8337
8355
|
},
|
|
@@ -8342,7 +8360,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
|
|
|
8342
8360
|
}
|
|
8343
8361
|
|
|
8344
8362
|
// src/components/planner/ChannelContribution.tsx
|
|
8345
|
-
var
|
|
8363
|
+
var import_jsx_runtime68 = require("react/jsx-runtime");
|
|
8346
8364
|
var money = (n) => "$" + Math.round(n).toLocaleString();
|
|
8347
8365
|
function ChannelContribution({
|
|
8348
8366
|
channels = [],
|
|
@@ -8358,9 +8376,9 @@ function ChannelContribution({
|
|
|
8358
8376
|
const grand = total !== void 0 ? total : base + bonus;
|
|
8359
8377
|
const pct = (v) => grand ? v / grand * 100 : 0;
|
|
8360
8378
|
const spendTotal = channels.reduce((s, c) => s + Number(String(c.spend || 0).replace(/[^0-9.]/g, "")), 0);
|
|
8361
|
-
return /* @__PURE__ */ (0,
|
|
8362
|
-
loading ? /* @__PURE__ */ (0,
|
|
8363
|
-
channels.map((c) => /* @__PURE__ */ (0,
|
|
8379
|
+
return /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
|
|
8380
|
+
loading ? /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { className: "fd-skel", style: { height: 34, borderRadius: "var(--r-sm)" } }) : /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "fd-row", style: { height: 34, borderRadius: "var(--r-sm)", overflow: "hidden", gap: 2, background: "var(--surface-3)" }, children: [
|
|
8381
|
+
channels.map((c) => /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
|
|
8364
8382
|
"span",
|
|
8365
8383
|
{
|
|
8366
8384
|
title: c.name + " \xB7 " + c.crp.toFixed(1) + " CRP",
|
|
@@ -8369,7 +8387,7 @@ function ChannelContribution({
|
|
|
8369
8387
|
},
|
|
8370
8388
|
c.name
|
|
8371
8389
|
)),
|
|
8372
|
-
bonus > 0 ? /* @__PURE__ */ (0,
|
|
8390
|
+
bonus > 0 ? /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
|
|
8373
8391
|
"span",
|
|
8374
8392
|
{
|
|
8375
8393
|
title: "Surround-sound bonus +" + bonusPct + "%",
|
|
@@ -8378,18 +8396,18 @@ function ChannelContribution({
|
|
|
8378
8396
|
}
|
|
8379
8397
|
) : null
|
|
8380
8398
|
] }),
|
|
8381
|
-
showTable ? /* @__PURE__ */ (0,
|
|
8382
|
-
/* @__PURE__ */ (0,
|
|
8383
|
-
/* @__PURE__ */ (0,
|
|
8384
|
-
/* @__PURE__ */ (0,
|
|
8385
|
-
/* @__PURE__ */ (0,
|
|
8386
|
-
/* @__PURE__ */ (0,
|
|
8387
|
-
/* @__PURE__ */ (0,
|
|
8399
|
+
showTable ? /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("table", { className: "fd-table", style: { fontSize: "var(--body-sm-size)" }, children: [
|
|
8400
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("tr", { children: [
|
|
8401
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsx)("th", { style: { width: "34%" }, children: "Channel" }),
|
|
8402
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsx)("th", { style: { width: "16%" }, children: "Weight" }),
|
|
8403
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsx)("th", { className: "is-num", style: { width: "16%" }, children: "Spend" }),
|
|
8404
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsx)("th", { className: "is-num", style: { width: "17%" }, children: "CRP" }),
|
|
8405
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsx)("th", { className: "is-num", style: { width: "17%" }, children: "Share" })
|
|
8388
8406
|
] }) }),
|
|
8389
|
-
/* @__PURE__ */ (0,
|
|
8390
|
-
channels.map((c) => /* @__PURE__ */ (0,
|
|
8391
|
-
/* @__PURE__ */ (0,
|
|
8392
|
-
/* @__PURE__ */ (0,
|
|
8407
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("tbody", { children: [
|
|
8408
|
+
channels.map((c) => /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("tr", { children: [
|
|
8409
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(ChannelTag, { channel: c.name, size: "sm" }) }),
|
|
8410
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
|
|
8393
8411
|
"span",
|
|
8394
8412
|
{
|
|
8395
8413
|
className: "fd-badge fd-badge-neutral",
|
|
@@ -8398,38 +8416,38 @@ function ChannelContribution({
|
|
|
8398
8416
|
children: "weight " + (channelWeightOf(c.name) || 0)
|
|
8399
8417
|
}
|
|
8400
8418
|
) }),
|
|
8401
|
-
/* @__PURE__ */ (0,
|
|
8402
|
-
/* @__PURE__ */ (0,
|
|
8403
|
-
/* @__PURE__ */ (0,
|
|
8419
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsx)("td", { className: "is-num", children: c.spend }),
|
|
8420
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsx)("td", { className: "is-num", children: c.crp.toFixed(1) }),
|
|
8421
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("td", { className: "is-num", children: [
|
|
8404
8422
|
pct(c.crp).toFixed(0),
|
|
8405
8423
|
"%"
|
|
8406
8424
|
] })
|
|
8407
8425
|
] }, c.name)),
|
|
8408
|
-
bonus > 0 ? /* @__PURE__ */ (0,
|
|
8409
|
-
/* @__PURE__ */ (0,
|
|
8410
|
-
/* @__PURE__ */ (0,
|
|
8426
|
+
bonus > 0 ? /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("tr", { children: [
|
|
8427
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("span", { className: "fd-row", style: { gap: 9, fontWeight: 600 }, children: [
|
|
8428
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { style: { width: 9, height: 9, borderRadius: 2, background: "repeating-linear-gradient(135deg,var(--csi-3-mark) 0 3px,var(--csi-2-mark) 3px 6px)", flex: "none" } }),
|
|
8411
8429
|
"Surround-sound bonus"
|
|
8412
8430
|
] }) }),
|
|
8413
|
-
/* @__PURE__ */ (0,
|
|
8431
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("span", { className: "fd-badge fd-badge-success", style: { height: 20, fontSize: 11 }, children: [
|
|
8414
8432
|
"+",
|
|
8415
8433
|
bonusPct,
|
|
8416
8434
|
"% of +",
|
|
8417
8435
|
bonusMax,
|
|
8418
8436
|
"%"
|
|
8419
8437
|
] }) }),
|
|
8420
|
-
/* @__PURE__ */ (0,
|
|
8421
|
-
/* @__PURE__ */ (0,
|
|
8422
|
-
/* @__PURE__ */ (0,
|
|
8438
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsx)("td", { className: "is-num fd-muted", children: "\u2014" }),
|
|
8439
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsx)("td", { className: "is-num", children: bonus.toFixed(1) }),
|
|
8440
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("td", { className: "is-num", children: [
|
|
8423
8441
|
pct(bonus).toFixed(0),
|
|
8424
8442
|
"%"
|
|
8425
8443
|
] })
|
|
8426
8444
|
] }) : null,
|
|
8427
|
-
/* @__PURE__ */ (0,
|
|
8428
|
-
/* @__PURE__ */ (0,
|
|
8429
|
-
/* @__PURE__ */ (0,
|
|
8430
|
-
/* @__PURE__ */ (0,
|
|
8431
|
-
/* @__PURE__ */ (0,
|
|
8432
|
-
/* @__PURE__ */ (0,
|
|
8445
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("tr", { style: { background: "var(--surface-2)" }, children: [
|
|
8446
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsx)("td", { style: { fontWeight: 700 }, children: "Campus total" }),
|
|
8447
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsx)("td", {}),
|
|
8448
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsx)("td", { className: "is-num", style: { fontWeight: 700 }, children: money(spendTotal) }),
|
|
8449
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsx)("td", { className: "is-num", style: { fontWeight: 700 }, children: grand.toFixed(1) }),
|
|
8450
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsx)("td", { className: "is-num", style: { fontWeight: 700 }, children: "100%" })
|
|
8433
8451
|
] })
|
|
8434
8452
|
] })
|
|
8435
8453
|
] }) : null
|
|
@@ -8437,8 +8455,8 @@ function ChannelContribution({
|
|
|
8437
8455
|
}
|
|
8438
8456
|
|
|
8439
8457
|
// src/components/planner/BudgetReallocator.tsx
|
|
8440
|
-
var
|
|
8441
|
-
var
|
|
8458
|
+
var React37 = __toESM(require("react"), 1);
|
|
8459
|
+
var import_jsx_runtime69 = require("react/jsx-runtime");
|
|
8442
8460
|
var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
|
|
8443
8461
|
function BudgetReallocator({
|
|
8444
8462
|
campus,
|
|
@@ -8453,8 +8471,8 @@ function BudgetReallocator({
|
|
|
8453
8471
|
onCancel,
|
|
8454
8472
|
className = ""
|
|
8455
8473
|
}) {
|
|
8456
|
-
const [draft, setDraft] =
|
|
8457
|
-
|
|
8474
|
+
const [draft, setDraft] = React37.useState(spend);
|
|
8475
|
+
React37.useEffect(() => setDraft(spend), [spend]);
|
|
8458
8476
|
const dirty = draft !== spend;
|
|
8459
8477
|
const nextCrp = scoreFor ? scoreFor(draft) : crp;
|
|
8460
8478
|
const nextBand = bandFor(nextCrp);
|
|
@@ -8469,24 +8487,24 @@ function BudgetReallocator({
|
|
|
8469
8487
|
setDraft(spend);
|
|
8470
8488
|
if (onCancel) onCancel();
|
|
8471
8489
|
};
|
|
8472
|
-
return /* @__PURE__ */ (0,
|
|
8490
|
+
return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(
|
|
8473
8491
|
"div",
|
|
8474
8492
|
{
|
|
8475
8493
|
className: ["fd-stack", className].filter(Boolean).join(" "),
|
|
8476
8494
|
style: { gap: 14, padding: 18, border: "1px solid " + (dirty ? "var(--border-brand)" : "var(--border)"), borderRadius: "var(--r-lg)", background: dirty ? "var(--surface-brand)" : "var(--surface)", color: "var(--text)", transition: "background var(--dur-base) var(--ease),border-color var(--dur-base) var(--ease)" },
|
|
8477
8495
|
children: [
|
|
8478
|
-
/* @__PURE__ */ (0,
|
|
8479
|
-
/* @__PURE__ */ (0,
|
|
8480
|
-
/* @__PURE__ */ (0,
|
|
8481
|
-
dirty ? /* @__PURE__ */ (0,
|
|
8482
|
-
/* @__PURE__ */ (0,
|
|
8483
|
-
/* @__PURE__ */ (0,
|
|
8496
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
|
|
8497
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fd-h4", style: { flex: 1, minWidth: 140 }, children: campus }),
|
|
8498
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)(CsiBadge, { band: nowBand, crp, size: "medium" }),
|
|
8499
|
+
dirty ? /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(import_jsx_runtime69.Fragment, { children: [
|
|
8500
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("i", { className: "ph ph-arrow-right fd-muted", "aria-hidden": "true" }),
|
|
8501
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)(CsiBadge, { band: nextBand, crp: nextCrp, size: "medium", preview: true })
|
|
8484
8502
|
] }) : null
|
|
8485
8503
|
] }),
|
|
8486
|
-
/* @__PURE__ */ (0,
|
|
8487
|
-
/* @__PURE__ */ (0,
|
|
8488
|
-
dirty ? /* @__PURE__ */ (0,
|
|
8489
|
-
/* @__PURE__ */ (0,
|
|
8504
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fd-slider", children: [
|
|
8505
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
|
|
8506
|
+
dirty ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fd-slider-chip", style: { left: pct + "%", background: delta < 0 ? "var(--danger-solid)" : "var(--ok-solid)" }, children: (delta < 0 ? "\u2212$" : "+$") + Math.abs(delta).toLocaleString() }) : null,
|
|
8507
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
|
|
8490
8508
|
"input",
|
|
8491
8509
|
{
|
|
8492
8510
|
type: "range",
|
|
@@ -8502,13 +8520,13 @@ function BudgetReallocator({
|
|
|
8502
8520
|
}
|
|
8503
8521
|
)
|
|
8504
8522
|
] }),
|
|
8505
|
-
/* @__PURE__ */ (0,
|
|
8506
|
-
/* @__PURE__ */ (0,
|
|
8507
|
-
/* @__PURE__ */ (0,
|
|
8508
|
-
/* @__PURE__ */ (0,
|
|
8523
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
|
|
8524
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("span", { className: "fd-stack", style: { gap: 2, flex: 1, minWidth: 150 }, children: [
|
|
8525
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fd-num", style: { fontSize: 19, fontWeight: 700 }, children: "$" + draft.toLocaleString() }),
|
|
8526
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "fd-body-sm fd-muted", children: "Arrow keys step $100, shift+arrow $1,000. Escape reverts." })
|
|
8509
8527
|
] }),
|
|
8510
|
-
/* @__PURE__ */ (0,
|
|
8511
|
-
/* @__PURE__ */ (0,
|
|
8528
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("button", { type: "button", className: "fd-btn fd-btn-ghost", disabled: !dirty, onClick: revert, children: "Cancel" }),
|
|
8529
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
|
|
8512
8530
|
"button",
|
|
8513
8531
|
{
|
|
8514
8532
|
type: "button",
|
|
@@ -8527,7 +8545,7 @@ function BudgetReallocator({
|
|
|
8527
8545
|
}
|
|
8528
8546
|
|
|
8529
8547
|
// src/components/planner/SurroundSound.tsx
|
|
8530
|
-
var
|
|
8548
|
+
var import_jsx_runtime70 = require("react/jsx-runtime");
|
|
8531
8549
|
var CATEGORIES = [
|
|
8532
8550
|
{ key: "ooh", label: "OOH", icon: "flag-banner", color: "var(--ch-ooh)" },
|
|
8533
8551
|
{ key: "transit", label: "Transit", icon: "bus", color: "var(--ch-transit)" },
|
|
@@ -8539,26 +8557,26 @@ var CATEGORIES = [
|
|
|
8539
8557
|
function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost, className = "" }) {
|
|
8540
8558
|
const earned = Math.max(0, Math.min(1, bonusPct / bonusMax));
|
|
8541
8559
|
const single = present.length <= 2;
|
|
8542
|
-
return /* @__PURE__ */ (0,
|
|
8543
|
-
/* @__PURE__ */ (0,
|
|
8560
|
+
return /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, children: [
|
|
8561
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: CATEGORIES.map((c) => {
|
|
8544
8562
|
const on = present.includes(c.key);
|
|
8545
|
-
return /* @__PURE__ */ (0,
|
|
8563
|
+
return /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)(
|
|
8546
8564
|
"span",
|
|
8547
8565
|
{
|
|
8548
8566
|
title: c.label + (on ? " \u2014 present" : " \u2014 not bought"),
|
|
8549
8567
|
style: { display: "flex", flexDirection: "column", alignItems: "center", gap: 5, width: 62, padding: "10px 0", borderRadius: "var(--r-md)", border: "1px solid " + (on ? "var(--csi-2-edge)" : "var(--border)"), background: on ? "var(--csi-2-fill)" : "var(--surface-2)", color: on ? "var(--csi-2-text)" : "var(--text-disabled)" },
|
|
8550
8568
|
children: [
|
|
8551
|
-
/* @__PURE__ */ (0,
|
|
8552
|
-
/* @__PURE__ */ (0,
|
|
8569
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)("i", { className: "ph ph-" + c.icon, style: { fontSize: 19, color: on ? c.color : "var(--text-muted)" }, "aria-hidden": "true" }),
|
|
8570
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)("span", { style: { fontSize: 10.5, fontWeight: 700 }, children: c.label })
|
|
8553
8571
|
]
|
|
8554
8572
|
},
|
|
8555
8573
|
c.key
|
|
8556
8574
|
);
|
|
8557
8575
|
}) }),
|
|
8558
|
-
/* @__PURE__ */ (0,
|
|
8559
|
-
/* @__PURE__ */ (0,
|
|
8560
|
-
/* @__PURE__ */ (0,
|
|
8561
|
-
/* @__PURE__ */ (0,
|
|
8576
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("div", { className: "fd-stack", style: { gap: 8 }, children: [
|
|
8577
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
|
|
8578
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)("span", { className: "fd-label-lg", children: "Surround-sound bonus earned" }),
|
|
8579
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("span", { className: "fd-num", style: { color: single ? "var(--warn-text)" : "var(--csi-3-mark)", fontWeight: 700 }, children: [
|
|
8562
8580
|
"+",
|
|
8563
8581
|
bonusPct,
|
|
8564
8582
|
"% of +",
|
|
@@ -8566,8 +8584,8 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
|
|
|
8566
8584
|
"%"
|
|
8567
8585
|
] })
|
|
8568
8586
|
] }),
|
|
8569
|
-
/* @__PURE__ */ (0,
|
|
8570
|
-
/* @__PURE__ */ (0,
|
|
8587
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)("div", { style: { height: 8, borderRadius: "var(--r-xs)", background: "var(--surface-3)", overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("div", { style: { height: "100%", width: earned * 100 + "%", background: "var(--csi-3-mark)", borderRadius: "inherit", transition: "width var(--dur-slow) var(--ease)" } }) }),
|
|
8588
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: [
|
|
8571
8589
|
present.length,
|
|
8572
8590
|
" of 6 channel categories present.",
|
|
8573
8591
|
" ",
|
|
@@ -8579,7 +8597,7 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
|
|
|
8579
8597
|
}
|
|
8580
8598
|
|
|
8581
8599
|
// src/components/planner/Importance.tsx
|
|
8582
|
-
var
|
|
8600
|
+
var import_jsx_runtime71 = require("react/jsx-runtime");
|
|
8583
8601
|
var IMPORTANCE_LEVELS = [
|
|
8584
8602
|
{ id: "nudge", rank: 1, label: "Nudge", icon: "feather", description: "Breaks a tie, nothing more." },
|
|
8585
8603
|
{ id: "lean", rank: 2, label: "Lean", icon: "arrow-bend-up-right", description: "A mild preference between otherwise equal options." },
|
|
@@ -8609,23 +8627,23 @@ function importanceTokens(id) {
|
|
|
8609
8627
|
function ImportanceTag({ level, showLabel = true, size = "sm", className = "" }) {
|
|
8610
8628
|
const lvl = importanceLevel(level);
|
|
8611
8629
|
const t = importanceTokens(level);
|
|
8612
|
-
return /* @__PURE__ */ (0,
|
|
8630
|
+
return /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)(
|
|
8613
8631
|
"span",
|
|
8614
8632
|
{
|
|
8615
8633
|
className: ["fd-imp-tag", size === "md" ? "is-md" : "", className].filter(Boolean).join(" "),
|
|
8616
8634
|
style: { background: t.fill, borderColor: t.edge, color: t.text },
|
|
8617
8635
|
title: lvl.label + " \u2014 " + lvl.description,
|
|
8618
8636
|
children: [
|
|
8619
|
-
/* @__PURE__ */ (0,
|
|
8620
|
-
showLabel ? lvl.label : /* @__PURE__ */ (0,
|
|
8637
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)("i", { className: "ph ph-" + lvl.icon, "aria-hidden": "true" }),
|
|
8638
|
+
showLabel ? lvl.label : /* @__PURE__ */ (0, import_jsx_runtime71.jsx)("span", { className: "fd-sr", children: lvl.label })
|
|
8621
8639
|
]
|
|
8622
8640
|
}
|
|
8623
8641
|
);
|
|
8624
8642
|
}
|
|
8625
8643
|
|
|
8626
8644
|
// src/components/planner/PreferenceMeter.tsx
|
|
8627
|
-
var
|
|
8628
|
-
var
|
|
8645
|
+
var React38 = __toESM(require("react"), 1);
|
|
8646
|
+
var import_jsx_runtime72 = require("react/jsx-runtime");
|
|
8629
8647
|
function preferenceScore(criteria) {
|
|
8630
8648
|
const earned = criteria.reduce((n, c) => n + (Number(c.earned) || 0), 0);
|
|
8631
8649
|
const weight = criteria.reduce((n, c) => n + (Number(c.weight) || 0), 0);
|
|
@@ -8654,8 +8672,8 @@ function PreferenceMeter({
|
|
|
8654
8672
|
className = ""
|
|
8655
8673
|
}) {
|
|
8656
8674
|
const value = score == null ? preferenceScore(criteria) : score;
|
|
8657
|
-
const segments =
|
|
8658
|
-
return /* @__PURE__ */ (0,
|
|
8675
|
+
const segments = React38.useMemo(() => preferenceSegments(criteria), [criteria]);
|
|
8676
|
+
return /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
|
|
8659
8677
|
ScoreMeter,
|
|
8660
8678
|
{
|
|
8661
8679
|
score: value,
|
|
@@ -8667,22 +8685,22 @@ function PreferenceMeter({
|
|
|
8667
8685
|
placement,
|
|
8668
8686
|
className,
|
|
8669
8687
|
breakdownLabel: breakdownTitle,
|
|
8670
|
-
breakdown: /* @__PURE__ */ (0,
|
|
8671
|
-
/* @__PURE__ */ (0,
|
|
8672
|
-
/* @__PURE__ */ (0,
|
|
8673
|
-
/* @__PURE__ */ (0,
|
|
8688
|
+
breakdown: /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { className: "fd-prefbreak", children: [
|
|
8689
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("div", { className: "fd-prefbreak-head", children: [
|
|
8690
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsx)("span", { className: "fd-label-lg", children: breakdownTitle }),
|
|
8691
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsx)("span", { className: "fd-prefbreak-score fd-tabular", children: Math.round(value) })
|
|
8674
8692
|
] }),
|
|
8675
|
-
/* @__PURE__ */ (0,
|
|
8693
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsx)("ul", { className: "fd-prefbreak-list", children: criteria.map((c) => {
|
|
8676
8694
|
const pct = c.weight > 0 ? Math.round((Number(c.earned) || 0) / c.weight * 100) : 0;
|
|
8677
|
-
return /* @__PURE__ */ (0,
|
|
8678
|
-
/* @__PURE__ */ (0,
|
|
8679
|
-
/* @__PURE__ */ (0,
|
|
8680
|
-
/* @__PURE__ */ (0,
|
|
8681
|
-
c.note ? /* @__PURE__ */ (0,
|
|
8695
|
+
return /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("li", { className: pct === 0 ? "fd-prefbreak-item is-unmet" : "fd-prefbreak-item", children: [
|
|
8696
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsx)(ImportanceTag, { level: c.importance }),
|
|
8697
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("span", { className: "fd-prefbreak-text", children: [
|
|
8698
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsx)("span", { className: "fd-prefbreak-label", children: c.label }),
|
|
8699
|
+
c.note ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("span", { className: "fd-prefbreak-note", children: c.note }) : null
|
|
8682
8700
|
] }),
|
|
8683
|
-
/* @__PURE__ */ (0,
|
|
8701
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsxs)("span", { className: "fd-prefbreak-val fd-tabular", children: [
|
|
8684
8702
|
Math.round(Number(c.earned) || 0),
|
|
8685
|
-
/* @__PURE__ */ (0,
|
|
8703
|
+
/* @__PURE__ */ (0, import_jsx_runtime72.jsx)("span", { className: "fd-prefbreak-sep", children: "/" }),
|
|
8686
8704
|
Math.round(c.weight)
|
|
8687
8705
|
] })
|
|
8688
8706
|
] }, c.id);
|
|
@@ -8693,10 +8711,10 @@ function PreferenceMeter({
|
|
|
8693
8711
|
}
|
|
8694
8712
|
|
|
8695
8713
|
// src/components/chat/AgentChatPanel.tsx
|
|
8696
|
-
var
|
|
8714
|
+
var React44 = __toESM(require("react"), 1);
|
|
8697
8715
|
|
|
8698
8716
|
// src/components/chat/chatEngine.ts
|
|
8699
|
-
var
|
|
8717
|
+
var React39 = __toESM(require("react"), 1);
|
|
8700
8718
|
var CHAT_UNAVAILABLE = "chat_unavailable";
|
|
8701
8719
|
var JOB_PENDING = ["queued", "running"];
|
|
8702
8720
|
var JOB_SUCCESS = ["completed", "recovered"];
|
|
@@ -8750,22 +8768,22 @@ function useChatEngine(opts) {
|
|
|
8750
8768
|
onClear,
|
|
8751
8769
|
onFeedback
|
|
8752
8770
|
} = opts || {};
|
|
8753
|
-
const [status, setStatus] =
|
|
8754
|
-
const [threadId, setThreadId] =
|
|
8755
|
-
const [messages, setMessages] =
|
|
8756
|
-
const [queue, setQueue] =
|
|
8757
|
-
const [fatal, setFatal] =
|
|
8758
|
-
const [busy, setBusy] =
|
|
8759
|
-
const [turnStartedAt, setTurnStartedAt] =
|
|
8760
|
-
const listRef =
|
|
8761
|
-
const queueRef =
|
|
8762
|
-
const busyRef =
|
|
8763
|
-
const stoppedRef =
|
|
8764
|
-
const abortRef =
|
|
8765
|
-
const serverCount =
|
|
8766
|
-
const threadRef =
|
|
8767
|
-
const mounted =
|
|
8768
|
-
|
|
8771
|
+
const [status, setStatus] = React39.useState("idle");
|
|
8772
|
+
const [threadId, setThreadId] = React39.useState(null);
|
|
8773
|
+
const [messages, setMessages] = React39.useState([]);
|
|
8774
|
+
const [queue, setQueue] = React39.useState([]);
|
|
8775
|
+
const [fatal, setFatal] = React39.useState(null);
|
|
8776
|
+
const [busy, setBusy] = React39.useState(false);
|
|
8777
|
+
const [turnStartedAt, setTurnStartedAt] = React39.useState(null);
|
|
8778
|
+
const listRef = React39.useRef([]);
|
|
8779
|
+
const queueRef = React39.useRef([]);
|
|
8780
|
+
const busyRef = React39.useRef(false);
|
|
8781
|
+
const stoppedRef = React39.useRef(false);
|
|
8782
|
+
const abortRef = React39.useRef(null);
|
|
8783
|
+
const serverCount = React39.useRef(0);
|
|
8784
|
+
const threadRef = React39.useRef(null);
|
|
8785
|
+
const mounted = React39.useRef(true);
|
|
8786
|
+
React39.useEffect(() => {
|
|
8769
8787
|
mounted.current = true;
|
|
8770
8788
|
return () => {
|
|
8771
8789
|
mounted.current = false;
|
|
@@ -8787,14 +8805,14 @@ function useChatEngine(opts) {
|
|
|
8787
8805
|
}
|
|
8788
8806
|
return false;
|
|
8789
8807
|
};
|
|
8790
|
-
const loadThread =
|
|
8808
|
+
const loadThread = React39.useCallback(async (id) => {
|
|
8791
8809
|
const data = await apiAdapter.getThread(id);
|
|
8792
8810
|
const list = [...data && data.messages || []];
|
|
8793
8811
|
serverCount.current = list.length;
|
|
8794
8812
|
commit(list);
|
|
8795
8813
|
return list;
|
|
8796
8814
|
}, [apiAdapter]);
|
|
8797
|
-
|
|
8815
|
+
React39.useEffect(() => {
|
|
8798
8816
|
if (!apiAdapter) {
|
|
8799
8817
|
setStatus("idle");
|
|
8800
8818
|
setFatal(null);
|
|
@@ -9007,7 +9025,7 @@ function useChatEngine(opts) {
|
|
|
9007
9025
|
await dispatchTurn(turn);
|
|
9008
9026
|
}
|
|
9009
9027
|
}
|
|
9010
|
-
const send =
|
|
9028
|
+
const send = React39.useCallback((text, attachments) => {
|
|
9011
9029
|
const body = (text || "").trim();
|
|
9012
9030
|
if (!body && !(attachments && attachments.length)) return;
|
|
9013
9031
|
if (status === "disconnected") return;
|
|
@@ -9017,7 +9035,7 @@ function useChatEngine(opts) {
|
|
|
9017
9035
|
stoppedRef.current = false;
|
|
9018
9036
|
drain();
|
|
9019
9037
|
}, [status]);
|
|
9020
|
-
const stop =
|
|
9038
|
+
const stop = React39.useCallback(() => {
|
|
9021
9039
|
stoppedRef.current = true;
|
|
9022
9040
|
const ac = abortRef.current;
|
|
9023
9041
|
if (ac) {
|
|
@@ -9036,11 +9054,11 @@ function useChatEngine(opts) {
|
|
|
9036
9054
|
store.del(STORAGE_PREFIX + threadRef.current);
|
|
9037
9055
|
}
|
|
9038
9056
|
}, [apiAdapter]);
|
|
9039
|
-
const removeQueued =
|
|
9057
|
+
const removeQueued = React39.useCallback((id) => {
|
|
9040
9058
|
queueRef.current = queueRef.current.filter((t) => t.id !== id);
|
|
9041
9059
|
setQueue(queueRef.current.slice());
|
|
9042
9060
|
}, []);
|
|
9043
|
-
const retry =
|
|
9061
|
+
const retry = React39.useCallback(() => {
|
|
9044
9062
|
const list = listRef.current;
|
|
9045
9063
|
let at = -1;
|
|
9046
9064
|
for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
|
|
@@ -9056,19 +9074,19 @@ function useChatEngine(opts) {
|
|
|
9056
9074
|
setQueue(queueRef.current.slice());
|
|
9057
9075
|
drain();
|
|
9058
9076
|
}, []);
|
|
9059
|
-
const clear =
|
|
9077
|
+
const clear = React39.useCallback(() => {
|
|
9060
9078
|
commit([]);
|
|
9061
9079
|
serverCount.current = 0;
|
|
9062
9080
|
queueRef.current = [];
|
|
9063
9081
|
setQueue([]);
|
|
9064
9082
|
onClear && onClear();
|
|
9065
9083
|
}, [onClear]);
|
|
9066
|
-
const setFeedback =
|
|
9084
|
+
const setFeedback = React39.useCallback((id, value) => {
|
|
9067
9085
|
patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
|
|
9068
9086
|
const msg = listRef.current.find((m) => m.id === id);
|
|
9069
9087
|
onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
|
|
9070
9088
|
}, [onFeedback]);
|
|
9071
|
-
const reload =
|
|
9089
|
+
const reload = React39.useCallback(async () => {
|
|
9072
9090
|
if (!threadRef.current) return;
|
|
9073
9091
|
setStatus("loading");
|
|
9074
9092
|
try {
|
|
@@ -9106,11 +9124,11 @@ var ChatKit = {
|
|
|
9106
9124
|
};
|
|
9107
9125
|
|
|
9108
9126
|
// src/components/chat/ChatTranscript.tsx
|
|
9109
|
-
var
|
|
9127
|
+
var React41 = __toESM(require("react"), 1);
|
|
9110
9128
|
|
|
9111
9129
|
// src/components/chat/ChatTurn.tsx
|
|
9112
|
-
var
|
|
9113
|
-
var
|
|
9130
|
+
var React40 = __toESM(require("react"), 1);
|
|
9131
|
+
var import_jsx_runtime73 = require("react/jsx-runtime");
|
|
9114
9132
|
function JsonView({ value }) {
|
|
9115
9133
|
let text;
|
|
9116
9134
|
try {
|
|
@@ -9118,67 +9136,67 @@ function JsonView({ value }) {
|
|
|
9118
9136
|
} catch (e) {
|
|
9119
9137
|
text = String(value);
|
|
9120
9138
|
}
|
|
9121
|
-
return /* @__PURE__ */ (0,
|
|
9139
|
+
return /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(CodeBlock, { code: text, language: "json", collapseAfter: 18 });
|
|
9122
9140
|
}
|
|
9123
9141
|
function PacketCard({ packet, schema, render, onApply, applied }) {
|
|
9124
9142
|
if (!packet) return null;
|
|
9125
9143
|
const s = schema || {};
|
|
9126
9144
|
const invalid = packet.valid === false;
|
|
9127
9145
|
const title = s.heading || packet.type;
|
|
9128
|
-
return /* @__PURE__ */ (0,
|
|
9129
|
-
/* @__PURE__ */ (0,
|
|
9130
|
-
/* @__PURE__ */ (0,
|
|
9131
|
-
/* @__PURE__ */ (0,
|
|
9132
|
-
packet.repaired ? /* @__PURE__ */ (0,
|
|
9133
|
-
invalid ? /* @__PURE__ */ (0,
|
|
9146
|
+
return /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("section", { className: "fdc-packet" + (invalid ? " is-invalid" : ""), "aria-label": title, children: [
|
|
9147
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("header", { className: "fdc-packet-head", children: [
|
|
9148
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-" + (s.icon || "package"), "aria-hidden": "true" }),
|
|
9149
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fdc-packet-title", children: title }),
|
|
9150
|
+
packet.repaired ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fdc-packet-badge", children: "Repaired" }) : null,
|
|
9151
|
+
invalid ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fdc-packet-badge is-danger", children: "Invalid" }) : null
|
|
9134
9152
|
] }),
|
|
9135
|
-
invalid ? /* @__PURE__ */ (0,
|
|
9136
|
-
/* @__PURE__ */ (0,
|
|
9137
|
-
/* @__PURE__ */ (0,
|
|
9138
|
-
] }) : /* @__PURE__ */ (0,
|
|
9139
|
-
!invalid && onApply ? /* @__PURE__ */ (0,
|
|
9140
|
-
packet.repaired ? /* @__PURE__ */ (0,
|
|
9141
|
-
/* @__PURE__ */ (0,
|
|
9142
|
-
/* @__PURE__ */ (0,
|
|
9153
|
+
invalid ? /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "fdc-packet-alert", role: "alert", children: [
|
|
9154
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
9155
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { children: packet.error || "This result failed validation and can\u2019t be applied." })
|
|
9156
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("div", { className: "fdc-packet-body", children: render ? render(packet) : /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(JsonView, { value: packet.payload }) }),
|
|
9157
|
+
!invalid && onApply ? /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("footer", { className: "fdc-packet-foot", children: [
|
|
9158
|
+
packet.repaired ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fdc-packet-note", children: "Corrected by the backend after a first attempt." }) : /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", {}),
|
|
9159
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", disabled: applied, onClick: () => onApply(packet), children: [
|
|
9160
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-" + (applied ? "check" : "arrow-square-in"), "aria-hidden": "true" }),
|
|
9143
9161
|
applied ? "Applied" : s.applyLabel || "Apply"
|
|
9144
9162
|
] })
|
|
9145
9163
|
] }) : null
|
|
9146
9164
|
] });
|
|
9147
9165
|
}
|
|
9148
9166
|
function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
|
|
9149
|
-
const [open, setOpen] =
|
|
9167
|
+
const [open, setOpen] = React40.useState(defaultOpen);
|
|
9150
9168
|
if (!text) return null;
|
|
9151
|
-
return /* @__PURE__ */ (0,
|
|
9152
|
-
/* @__PURE__ */ (0,
|
|
9153
|
-
/* @__PURE__ */ (0,
|
|
9154
|
-
/* @__PURE__ */ (0,
|
|
9155
|
-
streaming ? /* @__PURE__ */ (0,
|
|
9156
|
-
/* @__PURE__ */ (0,
|
|
9157
|
-
/* @__PURE__ */ (0,
|
|
9158
|
-
/* @__PURE__ */ (0,
|
|
9169
|
+
return /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "fdc-think" + (open ? " is-open" : ""), children: [
|
|
9170
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
|
|
9171
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-brain", "aria-hidden": "true" }),
|
|
9172
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { children: streaming ? "Thinking" : durationMs ? "Thought for " + formatDuration(durationMs) : "Thought process" }),
|
|
9173
|
+
streaming ? /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("span", { className: "fdc-dots", "aria-hidden": "true", children: [
|
|
9174
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", {}),
|
|
9175
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", {}),
|
|
9176
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", {})
|
|
9159
9177
|
] }) : null,
|
|
9160
|
-
/* @__PURE__ */ (0,
|
|
9178
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-caret-" + (open ? "up" : "down"), "aria-hidden": "true" })
|
|
9161
9179
|
] }),
|
|
9162
|
-
open ? /* @__PURE__ */ (0,
|
|
9180
|
+
open ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("div", { className: "fdc-think-body", children: text }) : null
|
|
9163
9181
|
] });
|
|
9164
9182
|
}
|
|
9165
9183
|
function Citations({ items = [], onOpen }) {
|
|
9166
|
-
const [open, setOpen] =
|
|
9184
|
+
const [open, setOpen] = React40.useState(false);
|
|
9167
9185
|
if (!items.length) return null;
|
|
9168
|
-
return /* @__PURE__ */ (0,
|
|
9169
|
-
/* @__PURE__ */ (0,
|
|
9170
|
-
/* @__PURE__ */ (0,
|
|
9171
|
-
/* @__PURE__ */ (0,
|
|
9186
|
+
return /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "fdc-cites", children: [
|
|
9187
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
|
|
9188
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-quotes", "aria-hidden": "true" }),
|
|
9189
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("span", { children: [
|
|
9172
9190
|
items.length,
|
|
9173
9191
|
" source",
|
|
9174
9192
|
items.length === 1 ? "" : "s"
|
|
9175
9193
|
] }),
|
|
9176
|
-
/* @__PURE__ */ (0,
|
|
9194
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-caret-" + (open ? "up" : "down"), "aria-hidden": "true" })
|
|
9177
9195
|
] }),
|
|
9178
|
-
open ? /* @__PURE__ */ (0,
|
|
9179
|
-
/* @__PURE__ */ (0,
|
|
9180
|
-
c.url ? /* @__PURE__ */ (0,
|
|
9181
|
-
c.detail ? /* @__PURE__ */ (0,
|
|
9196
|
+
open ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("ol", { className: "fdc-cites-list", children: items.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("li", { children: [
|
|
9197
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fdc-cite-n fd-tabular", children: c.marker || i + 1 }),
|
|
9198
|
+
c.url ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("a", { href: c.url, target: "_blank", rel: "noopener noreferrer", onClick: onOpen ? (e) => onOpen(c, e) : void 0, children: c.title || c.url }) : /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { children: c.title || "Source" }),
|
|
9199
|
+
c.detail ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fdc-cite-detail", children: c.detail }) : null
|
|
9182
9200
|
] }, c.id || i)) }) : null
|
|
9183
9201
|
] });
|
|
9184
9202
|
}
|
|
@@ -9189,29 +9207,29 @@ function clampText(text, max) {
|
|
|
9189
9207
|
return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
|
|
9190
9208
|
}
|
|
9191
9209
|
function MessageBody({ message: m, ctx }) {
|
|
9192
|
-
const [expanded, setExpanded] =
|
|
9210
|
+
const [expanded, setExpanded] = React40.useState(false);
|
|
9193
9211
|
const isUser = m.role === "user";
|
|
9194
9212
|
const raw = m.text || "";
|
|
9195
9213
|
const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
|
|
9196
9214
|
const body = clamped != null ? clamped : raw;
|
|
9197
9215
|
const showMd = ctx.markdown && !isUser;
|
|
9198
|
-
return /* @__PURE__ */ (0,
|
|
9199
|
-
m.thinking && ctx.showThinking ? /* @__PURE__ */ (0,
|
|
9200
|
-
m.steps && m.steps.length && ctx.showSteps ? /* @__PURE__ */ (0,
|
|
9201
|
-
body ? /* @__PURE__ */ (0,
|
|
9202
|
-
showMd ? /* @__PURE__ */ (0,
|
|
9203
|
-
m.streaming ? /* @__PURE__ */ (0,
|
|
9216
|
+
return /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "fdc-body", children: [
|
|
9217
|
+
m.thinking && ctx.showThinking ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(ThinkingBlock, { text: m.thinking, durationMs: m.thinkingMs, streaming: m.streaming && !m.text }) : null,
|
|
9218
|
+
m.steps && m.steps.length && ctx.showSteps ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(StepList, { steps: m.steps, defaultOpen: m.steps.some((s) => s.status === "running"), dense: true }) : null,
|
|
9219
|
+
body ? /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "fdc-text" + (isUser ? " is-user" : ""), children: [
|
|
9220
|
+
showMd ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(Markdown, { source: body, headingOffset: 2, codeProps: { collapseAfter: 22 }, renderCitation: ctx.renderCitation }) : /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("div", { className: "fdc-plain", children: body }),
|
|
9221
|
+
m.streaming ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fdc-caret", "aria-hidden": "true" }) : null
|
|
9204
9222
|
] }) : null,
|
|
9205
|
-
clamped != null ? /* @__PURE__ */ (0,
|
|
9206
|
-
/* @__PURE__ */ (0,
|
|
9223
|
+
clamped != null ? /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(true), children: [
|
|
9224
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-caret-down", "aria-hidden": "true" }),
|
|
9207
9225
|
"Show more",
|
|
9208
|
-
/* @__PURE__ */ (0,
|
|
9209
|
-
] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */ (0,
|
|
9210
|
-
/* @__PURE__ */ (0,
|
|
9226
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fdc-more-len fd-tabular", children: raw.length < 2e3 ? raw.length.toLocaleString() + " characters" : Math.round(raw.length / 100) / 10 + "k characters" })
|
|
9227
|
+
] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(false), children: [
|
|
9228
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-caret-up", "aria-hidden": "true" }),
|
|
9211
9229
|
"Show less"
|
|
9212
9230
|
] }) : null,
|
|
9213
|
-
m.attachments && m.attachments.length ? /* @__PURE__ */ (0,
|
|
9214
|
-
m.packet ? /* @__PURE__ */ (0,
|
|
9231
|
+
m.attachments && m.attachments.length ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(FileGrid, { files: m.attachments, onOpen: ctx.onOpenAttachment, tiles: true, maxHeight: ctx.attachmentHeight || 220, compact: ctx.narrow }) : null,
|
|
9232
|
+
m.packet ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
|
|
9215
9233
|
PacketCard,
|
|
9216
9234
|
{
|
|
9217
9235
|
packet: m.packet,
|
|
@@ -9221,44 +9239,44 @@ function MessageBody({ message: m, ctx }) {
|
|
|
9221
9239
|
applied: ctx.appliedPackets && ctx.appliedPackets[m.id]
|
|
9222
9240
|
}
|
|
9223
9241
|
) : null,
|
|
9224
|
-
m.citations && m.citations.length ? /* @__PURE__ */ (0,
|
|
9225
|
-
m.working ? /* @__PURE__ */ (0,
|
|
9226
|
-
/* @__PURE__ */ (0,
|
|
9227
|
-
/* @__PURE__ */ (0,
|
|
9228
|
-
/* @__PURE__ */ (0,
|
|
9229
|
-
/* @__PURE__ */ (0,
|
|
9242
|
+
m.citations && m.citations.length ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(Citations, { items: m.citations, onOpen: ctx.onOpenCitation }) : null,
|
|
9243
|
+
m.working ? /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "fdc-working", role: "status", children: [
|
|
9244
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("span", { className: "fdc-dots", "aria-hidden": "true", children: [
|
|
9245
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", {}),
|
|
9246
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", {}),
|
|
9247
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", {})
|
|
9230
9248
|
] }),
|
|
9231
|
-
/* @__PURE__ */ (0,
|
|
9249
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("span", { className: "fdc-working-label", children: [
|
|
9232
9250
|
m.resumed ? "Resuming" : "Working",
|
|
9233
|
-
m.job && m.job.status ? /* @__PURE__ */ (0,
|
|
9251
|
+
m.job && m.job.status ? /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("span", { className: "fdc-working-job", children: [
|
|
9234
9252
|
" \xB7 ",
|
|
9235
9253
|
m.job.status
|
|
9236
9254
|
] }) : null,
|
|
9237
|
-
m.job && m.job.detail ? /* @__PURE__ */ (0,
|
|
9255
|
+
m.job && m.job.detail ? /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("span", { className: "fdc-working-job", children: [
|
|
9238
9256
|
" \xB7 ",
|
|
9239
9257
|
m.job.detail
|
|
9240
9258
|
] }) : null
|
|
9241
9259
|
] }),
|
|
9242
|
-
m.jobId ? /* @__PURE__ */ (0,
|
|
9260
|
+
m.jobId ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fdc-working-id fd-mono", children: String(m.jobId).slice(0, 12) }) : null
|
|
9243
9261
|
] }) : null,
|
|
9244
|
-
m.stopped ? /* @__PURE__ */ (0,
|
|
9245
|
-
/* @__PURE__ */ (0,
|
|
9262
|
+
m.stopped ? /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "fdc-stopped", children: [
|
|
9263
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
|
|
9246
9264
|
"Stopped"
|
|
9247
9265
|
] }) : null,
|
|
9248
|
-
m.error ? /* @__PURE__ */ (0,
|
|
9249
|
-
/* @__PURE__ */ (0,
|
|
9250
|
-
/* @__PURE__ */ (0,
|
|
9251
|
-
m.retryable && ctx.onRetry ? /* @__PURE__ */ (0,
|
|
9252
|
-
/* @__PURE__ */ (0,
|
|
9266
|
+
m.error ? /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "fdc-error", role: "alert", children: [
|
|
9267
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
9268
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fdc-error-text", children: ctx.errorCopy ? ctx.errorCopy(m.error) : m.error }),
|
|
9269
|
+
m.retryable && ctx.onRetry ? /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("button", { type: "button", className: "fdc-error-retry", onClick: ctx.onRetry, children: [
|
|
9270
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
|
|
9253
9271
|
"Retry"
|
|
9254
9272
|
] }) : null
|
|
9255
9273
|
] }) : null
|
|
9256
9274
|
] });
|
|
9257
9275
|
}
|
|
9258
9276
|
function useCopyRun() {
|
|
9259
|
-
const [done, setDone] =
|
|
9260
|
-
const t =
|
|
9261
|
-
|
|
9277
|
+
const [done, setDone] = React40.useState(false);
|
|
9278
|
+
const t = React40.useRef(null);
|
|
9279
|
+
React40.useEffect(() => () => {
|
|
9262
9280
|
if (t.current) clearTimeout(t.current);
|
|
9263
9281
|
}, []);
|
|
9264
9282
|
return [done, (text) => {
|
|
@@ -9278,16 +9296,16 @@ function RunActions({ group, ctx }) {
|
|
|
9278
9296
|
const isAssistant = group.role === "assistant";
|
|
9279
9297
|
const fb = last.feedback;
|
|
9280
9298
|
if (!ctx.messageActions) return null;
|
|
9281
|
-
return /* @__PURE__ */ (0,
|
|
9282
|
-
/* @__PURE__ */ (0,
|
|
9283
|
-
/* @__PURE__ */ (0,
|
|
9284
|
-
/* @__PURE__ */ (0,
|
|
9299
|
+
return /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "fdc-actions", role: "group", "aria-label": "Message actions", children: [
|
|
9300
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("button", { type: "button", className: "fdc-act" + (copied ? " is-done" : ""), onClick: () => copy(markdownToText(text)), "aria-label": "Copy message", children: [
|
|
9301
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-" + (copied ? "check" : "copy"), "aria-hidden": "true" }),
|
|
9302
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fdc-act-label", children: copied ? "Copied" : "Copy" })
|
|
9285
9303
|
] }),
|
|
9286
|
-
isAssistant && ctx.onRetry ? /* @__PURE__ */ (0,
|
|
9287
|
-
group.role === "user" && ctx.onEdit ? /* @__PURE__ */ (0,
|
|
9288
|
-
isAssistant && ctx.onFeedback ? /* @__PURE__ */ (0,
|
|
9289
|
-
/* @__PURE__ */ (0,
|
|
9290
|
-
/* @__PURE__ */ (0,
|
|
9304
|
+
isAssistant && ctx.onRetry ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("button", { type: "button", className: "fdc-act", onClick: ctx.onRetry, "aria-label": "Retry this turn", children: /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
|
|
9305
|
+
group.role === "user" && ctx.onEdit ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("button", { type: "button", className: "fdc-act", onClick: () => ctx.onEdit(last), "aria-label": "Edit and resend", children: /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-pencil-simple", "aria-hidden": "true" }) }) : null,
|
|
9306
|
+
isAssistant && ctx.onFeedback ? /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(React40.Fragment, { children: [
|
|
9307
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("button", { type: "button", className: "fdc-act" + (fb === "up" ? " is-on" : ""), onClick: () => ctx.onFeedback(last.id, "up"), "aria-pressed": fb === "up", "aria-label": "Good response", children: /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-thumbs-up", "aria-hidden": "true" }) }),
|
|
9308
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("button", { type: "button", className: "fdc-act" + (fb === "down" ? " is-on" : ""), onClick: () => ctx.onFeedback(last.id, "down"), "aria-pressed": fb === "down", "aria-label": "Bad response", children: /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-thumbs-down", "aria-hidden": "true" }) })
|
|
9291
9309
|
] }) : null,
|
|
9292
9310
|
ctx.extraActions ? ctx.extraActions(group) : null
|
|
9293
9311
|
] });
|
|
@@ -9297,22 +9315,22 @@ function ChatTurn({ group, ctx }) {
|
|
|
9297
9315
|
const name = isUser ? ctx.userName : group.author || ctx.assistantName;
|
|
9298
9316
|
const avatar = isUser ? ctx.userAvatar : ctx.assistantAvatar;
|
|
9299
9317
|
const stamp = group.messages[0].timestamp;
|
|
9300
|
-
return /* @__PURE__ */ (0,
|
|
9301
|
-
/* @__PURE__ */ (0,
|
|
9302
|
-
ctx.showAvatars ? /* @__PURE__ */ (0,
|
|
9303
|
-
/* @__PURE__ */ (0,
|
|
9304
|
-
stamp ? /* @__PURE__ */ (0,
|
|
9305
|
-
group.messages.some((m) => m.model) ? /* @__PURE__ */ (0,
|
|
9318
|
+
return /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("article", { className: "fdc-turn is-" + group.role, "aria-label": String(name) + (stamp ? " at " + formatClock(stamp) : ""), children: [
|
|
9319
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "fdc-turn-head", children: [
|
|
9320
|
+
ctx.showAvatars ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fdc-avatar is-" + group.role, "aria-hidden": "true", children: avatar ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("img", { src: avatar, alt: "" }) : isUser ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fdc-avatar-txt", children: (name || "You").slice(0, 1).toUpperCase() }) : /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-" + (ctx.assistantIcon || "sparkle") }) }) : null,
|
|
9321
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fdc-who", children: name }),
|
|
9322
|
+
stamp ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(RelativeTime, { className: "fdc-when", value: stamp }) : null,
|
|
9323
|
+
group.messages.some((m) => m.model) ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fdc-turn-model", children: group.messages.find((m) => m.model).model }) : null
|
|
9306
9324
|
] }),
|
|
9307
|
-
/* @__PURE__ */ (0,
|
|
9308
|
-
group.messages.map((m) => /* @__PURE__ */ (0,
|
|
9309
|
-
/* @__PURE__ */ (0,
|
|
9325
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "fdc-turn-body", children: [
|
|
9326
|
+
group.messages.map((m) => /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("div", { className: "fdc-msg" + (m.pending ? " is-pending" : ""), children: /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(MessageBody, { message: m, ctx }) }, m.id)),
|
|
9327
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)(RunActions, { group, ctx })
|
|
9310
9328
|
] })
|
|
9311
9329
|
] });
|
|
9312
9330
|
}
|
|
9313
9331
|
|
|
9314
9332
|
// src/components/chat/ChatTranscript.tsx
|
|
9315
|
-
var
|
|
9333
|
+
var import_jsx_runtime74 = require("react/jsx-runtime");
|
|
9316
9334
|
var GROUP_WINDOW = 6e4;
|
|
9317
9335
|
var STICK_PX = 100;
|
|
9318
9336
|
function groupMessages(list) {
|
|
@@ -9345,25 +9363,25 @@ function dayLabel(key) {
|
|
|
9345
9363
|
}
|
|
9346
9364
|
function Suggestions({ items = [], onPick }) {
|
|
9347
9365
|
if (!items.length) return null;
|
|
9348
|
-
return /* @__PURE__ */ (0,
|
|
9366
|
+
return /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("div", { className: "fdc-suggest", children: items.map((s, i) => {
|
|
9349
9367
|
const it = typeof s === "string" ? { label: s, text: s } : s;
|
|
9350
|
-
return /* @__PURE__ */ (0,
|
|
9351
|
-
it.icon ? /* @__PURE__ */ (0,
|
|
9352
|
-
/* @__PURE__ */ (0,
|
|
9353
|
-
/* @__PURE__ */ (0,
|
|
9354
|
-
it.description ? /* @__PURE__ */ (0,
|
|
9368
|
+
return /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("button", { type: "button", className: "fdc-suggest-item", onClick: () => onPick && onPick(it.text || it.label), children: [
|
|
9369
|
+
it.icon ? /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("i", { className: "ph ph-" + it.icon, "aria-hidden": "true" }) : null,
|
|
9370
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("span", { className: "fdc-suggest-text", children: [
|
|
9371
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsx)("span", { className: "fdc-suggest-label", children: it.label }),
|
|
9372
|
+
it.description ? /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("span", { className: "fdc-suggest-desc", children: it.description }) : null
|
|
9355
9373
|
] }),
|
|
9356
|
-
/* @__PURE__ */ (0,
|
|
9374
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsx)("i", { className: "ph ph-arrow-up-right fdc-suggest-go", "aria-hidden": "true" })
|
|
9357
9375
|
] }, it.id || i);
|
|
9358
9376
|
}) });
|
|
9359
9377
|
}
|
|
9360
9378
|
function LoadingTurns() {
|
|
9361
|
-
return /* @__PURE__ */ (0,
|
|
9362
|
-
/* @__PURE__ */ (0,
|
|
9363
|
-
/* @__PURE__ */ (0,
|
|
9364
|
-
/* @__PURE__ */ (0,
|
|
9365
|
-
/* @__PURE__ */ (0,
|
|
9366
|
-
/* @__PURE__ */ (0,
|
|
9379
|
+
return /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("div", { className: "fdc-skel", "aria-hidden": "true", children: [0, 1].map((i) => /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("div", { className: "fdc-skel-turn", children: [
|
|
9380
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsx)("div", { className: "fd-skel fd-skel-circle", style: { width: 22, height: 22 } }),
|
|
9381
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("div", { className: "fdc-skel-lines", children: [
|
|
9382
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsx)("div", { className: "fd-skel", style: { width: i ? "62%" : "44%", height: 11 } }),
|
|
9383
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsx)("div", { className: "fd-skel", style: { width: i ? "94%" : "78%", height: 11 } }),
|
|
9384
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsx)("div", { className: "fd-skel", style: { width: i ? "71%" : "56%", height: 11 } })
|
|
9367
9385
|
] })
|
|
9368
9386
|
] }, i)) });
|
|
9369
9387
|
}
|
|
@@ -9380,10 +9398,10 @@ function ChatTranscript({
|
|
|
9380
9398
|
renderEmpty,
|
|
9381
9399
|
className = ""
|
|
9382
9400
|
}) {
|
|
9383
|
-
const scroller =
|
|
9384
|
-
const stick =
|
|
9385
|
-
const [pill, setPill] =
|
|
9386
|
-
const seen =
|
|
9401
|
+
const scroller = React41.useRef(null);
|
|
9402
|
+
const stick = React41.useRef(true);
|
|
9403
|
+
const [pill, setPill] = React41.useState(0);
|
|
9404
|
+
const seen = React41.useRef(0);
|
|
9387
9405
|
const toBottom = (smooth) => {
|
|
9388
9406
|
const el = scroller.current;
|
|
9389
9407
|
if (!el) return;
|
|
@@ -9402,7 +9420,7 @@ function ChatTranscript({
|
|
|
9402
9420
|
seen.current = messages.length;
|
|
9403
9421
|
}
|
|
9404
9422
|
};
|
|
9405
|
-
|
|
9423
|
+
React41.useLayoutEffect(() => {
|
|
9406
9424
|
const el = scroller.current;
|
|
9407
9425
|
if (!el) return;
|
|
9408
9426
|
if (stick.current) {
|
|
@@ -9410,7 +9428,7 @@ function ChatTranscript({
|
|
|
9410
9428
|
seen.current = messages.length;
|
|
9411
9429
|
} else setPill(Math.max(0, messages.length - seen.current));
|
|
9412
9430
|
}, [messages]);
|
|
9413
|
-
|
|
9431
|
+
React41.useEffect(() => {
|
|
9414
9432
|
const el = scroller.current;
|
|
9415
9433
|
const inner = el && el.firstChild;
|
|
9416
9434
|
if (!el || !inner || typeof ResizeObserver === "undefined") return;
|
|
@@ -9420,38 +9438,38 @@ function ChatTranscript({
|
|
|
9420
9438
|
ro.observe(inner);
|
|
9421
9439
|
return () => ro.disconnect();
|
|
9422
9440
|
}, []);
|
|
9423
|
-
const groups =
|
|
9441
|
+
const groups = React41.useMemo(() => groupMessages(messages), [messages]);
|
|
9424
9442
|
const empty = !messages.length && status === "ready";
|
|
9425
|
-
return /* @__PURE__ */ (0,
|
|
9426
|
-
/* @__PURE__ */ (0,
|
|
9427
|
-
status === "loading" || status === "resolving" ? /* @__PURE__ */ (0,
|
|
9428
|
-
status === "disconnected" ? /* @__PURE__ */ (0,
|
|
9429
|
-
/* @__PURE__ */ (0,
|
|
9430
|
-
/* @__PURE__ */ (0,
|
|
9431
|
-
/* @__PURE__ */ (0,
|
|
9432
|
-
ctx.onReconnect ? /* @__PURE__ */ (0,
|
|
9433
|
-
/* @__PURE__ */ (0,
|
|
9443
|
+
return /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
|
|
9444
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
|
|
9445
|
+
status === "loading" || status === "resolving" ? /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(LoadingTurns, {}) : null,
|
|
9446
|
+
status === "disconnected" ? /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("div", { className: "fdc-dead", children: [
|
|
9447
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsx)("span", { className: "fdc-dead-icon", children: /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("i", { className: "ph ph-plugs", "aria-hidden": "true" }) }),
|
|
9448
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsx)("h3", { className: "fdc-dead-title", children: ctx.deadTitle || "The assistant isn\u2019t reachable" }),
|
|
9449
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsx)("p", { className: "fdc-dead-body", children: fatal === "chat_unavailable" ? "The service reported chat_unavailable. Nothing you type will be lost \u2014 reopen the panel once it\u2019s back." : "The thread couldn\u2019t be resolved" + (fatal ? " (" + fatal + ")" : "") + ". The composer stays disabled until it resolves." }),
|
|
9450
|
+
ctx.onReconnect ? /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("button", { type: "button", className: "fd-btn fd-btn-secondary fd-btn-sm", onClick: ctx.onReconnect, children: [
|
|
9451
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
|
|
9434
9452
|
"Try again"
|
|
9435
9453
|
] }) : null
|
|
9436
9454
|
] }) : null,
|
|
9437
|
-
empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */ (0,
|
|
9438
|
-
/* @__PURE__ */ (0,
|
|
9439
|
-
/* @__PURE__ */ (0,
|
|
9440
|
-
emptyDescription ? /* @__PURE__ */ (0,
|
|
9441
|
-
/* @__PURE__ */ (0,
|
|
9455
|
+
empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("div", { className: "fdc-empty", children: [
|
|
9456
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsx)("span", { className: "fdc-empty-icon", children: /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("i", { className: "ph ph-" + emptyIcon, "aria-hidden": "true" }) }),
|
|
9457
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsx)("h3", { className: "fdc-empty-title", children: emptyTitle }),
|
|
9458
|
+
emptyDescription ? /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("p", { className: "fdc-empty-body", children: emptyDescription }) : null,
|
|
9459
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsx)(Suggestions, { items: suggestions, onPick })
|
|
9442
9460
|
] }) : null,
|
|
9443
9461
|
groups.map((g, i) => {
|
|
9444
9462
|
const prev = groups[i - 1];
|
|
9445
9463
|
const k = dayKey(g.messages[0].timestamp);
|
|
9446
9464
|
const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
|
|
9447
|
-
return /* @__PURE__ */ (0,
|
|
9448
|
-
showDay ? /* @__PURE__ */ (0,
|
|
9449
|
-
/* @__PURE__ */ (0,
|
|
9465
|
+
return /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)(React41.Fragment, { children: [
|
|
9466
|
+
showDay ? /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("div", { className: "fdc-day", children: /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("span", { children: dayLabel(k) }) }) : null,
|
|
9467
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsx)(ChatTurn, { group: g, ctx })
|
|
9450
9468
|
] }, g.key || i);
|
|
9451
9469
|
})
|
|
9452
9470
|
] }),
|
|
9453
|
-
pill ? /* @__PURE__ */ (0,
|
|
9454
|
-
/* @__PURE__ */ (0,
|
|
9471
|
+
pill ? /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("button", { type: "button", className: "fdc-pill", onClick: () => toBottom(true), children: [
|
|
9472
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsx)("i", { className: "ph ph-arrow-down", "aria-hidden": "true" }),
|
|
9455
9473
|
pill,
|
|
9456
9474
|
" new message",
|
|
9457
9475
|
pill === 1 ? "" : "s"
|
|
@@ -9461,8 +9479,8 @@ function ChatTranscript({
|
|
|
9461
9479
|
var TranscriptKit = { groupMessages };
|
|
9462
9480
|
|
|
9463
9481
|
// src/components/chat/ChatComposer.tsx
|
|
9464
|
-
var
|
|
9465
|
-
var
|
|
9482
|
+
var React42 = __toESM(require("react"), 1);
|
|
9483
|
+
var import_jsx_runtime75 = require("react/jsx-runtime");
|
|
9466
9484
|
function ChatComposer({
|
|
9467
9485
|
onSubmit,
|
|
9468
9486
|
onStop,
|
|
@@ -9489,17 +9507,17 @@ function ChatComposer({
|
|
|
9489
9507
|
onReject,
|
|
9490
9508
|
onOpenAttachment
|
|
9491
9509
|
}) {
|
|
9492
|
-
const [text, setText] =
|
|
9493
|
-
const [trigger, setTrigger] =
|
|
9494
|
-
const [mentionItems, setMentionItems] =
|
|
9495
|
-
const [listening, setListening] =
|
|
9496
|
-
const [notice, setNotice] =
|
|
9497
|
-
const editor =
|
|
9498
|
-
const wrap =
|
|
9499
|
-
const stopVoice =
|
|
9510
|
+
const [text, setText] = React42.useState(draft || "");
|
|
9511
|
+
const [trigger, setTrigger] = React42.useState(null);
|
|
9512
|
+
const [mentionItems, setMentionItems] = React42.useState([]);
|
|
9513
|
+
const [listening, setListening] = React42.useState(false);
|
|
9514
|
+
const [notice, setNotice] = React42.useState(null);
|
|
9515
|
+
const editor = React42.useRef(null);
|
|
9516
|
+
const wrap = React42.useRef(null);
|
|
9517
|
+
const stopVoice = React42.useRef(null);
|
|
9500
9518
|
const staged = useStagedFiles(fileUploadHandler, { onError: () => {
|
|
9501
9519
|
} });
|
|
9502
|
-
|
|
9520
|
+
React42.useEffect(() => {
|
|
9503
9521
|
if (draft != null && draft !== text) setText(draft);
|
|
9504
9522
|
}, [draft]);
|
|
9505
9523
|
const change = (v) => {
|
|
@@ -9533,7 +9551,7 @@ function ChatComposer({
|
|
|
9533
9551
|
e.preventDefault();
|
|
9534
9552
|
staged.add(found.files);
|
|
9535
9553
|
};
|
|
9536
|
-
|
|
9554
|
+
React42.useEffect(() => {
|
|
9537
9555
|
if (!trigger || trigger.type !== "mention" || !mentionSources) {
|
|
9538
9556
|
setMentionItems([]);
|
|
9539
9557
|
return;
|
|
@@ -9551,7 +9569,7 @@ function ChatComposer({
|
|
|
9551
9569
|
const q = (trigger.query || "").toLowerCase();
|
|
9552
9570
|
setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
|
|
9553
9571
|
}, [trigger, mentionSources]);
|
|
9554
|
-
const slashItems =
|
|
9572
|
+
const slashItems = React42.useMemo(() => {
|
|
9555
9573
|
if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
|
|
9556
9574
|
const q = (trigger.query || "").toLowerCase();
|
|
9557
9575
|
return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
|
|
@@ -9565,7 +9583,7 @@ function ChatComposer({
|
|
|
9565
9583
|
description: it.description,
|
|
9566
9584
|
icon: it.icon,
|
|
9567
9585
|
meta: mention.meta,
|
|
9568
|
-
shortcut: slash.shortcut ? /* @__PURE__ */ (0,
|
|
9586
|
+
shortcut: slash.shortcut ? /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(KeyHint, { keys: slash.shortcut, size: "sm" }) : void 0,
|
|
9569
9587
|
onSelect: () => {
|
|
9570
9588
|
const insert = trigger.type === "slash" ? slash.immediate ? "/" + slash.id : "/" + slash.id + " " : "@" + (mention.value || mention.label) + " ";
|
|
9571
9589
|
editor.current && editor.current.replaceRange(trigger.from, trigger.to, insert);
|
|
@@ -9628,14 +9646,14 @@ function ChatComposer({
|
|
|
9628
9646
|
stopVoice.current = typeof res === "function" ? res : () => {
|
|
9629
9647
|
};
|
|
9630
9648
|
};
|
|
9631
|
-
return /* @__PURE__ */ (0,
|
|
9632
|
-
queue.length ? /* @__PURE__ */ (0,
|
|
9633
|
-
/* @__PURE__ */ (0,
|
|
9634
|
-
/* @__PURE__ */ (0,
|
|
9635
|
-
onRemoveQueued ? /* @__PURE__ */ (0,
|
|
9649
|
+
return /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)("div", { className: "fdc-composer" + (disabled ? " is-disabled" : "") + (narrow ? " is-narrow" : ""), children: [
|
|
9650
|
+
queue.length ? /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("div", { className: "fdc-queue", "aria-label": "Queued messages", children: queue.map((q) => /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)("div", { className: "fdc-queue-row", children: [
|
|
9651
|
+
/* @__PURE__ */ (0, import_jsx_runtime75.jsx)("i", { className: "ph ph-clock-countdown", "aria-hidden": "true" }),
|
|
9652
|
+
/* @__PURE__ */ (0, import_jsx_runtime75.jsx)("span", { className: "fdc-queue-text", children: q.text || (q.attachments ? q.attachments.length + " file(s)" : "") }),
|
|
9653
|
+
onRemoveQueued ? /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("button", { type: "button", className: "fdc-queue-x", onClick: () => onRemoveQueued(q.id), "aria-label": "Remove queued message", children: /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
|
|
9636
9654
|
] }, q.id)) }) : null,
|
|
9637
9655
|
sessionBar,
|
|
9638
|
-
/* @__PURE__ */ (0,
|
|
9656
|
+
/* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
|
|
9639
9657
|
Dropzone,
|
|
9640
9658
|
{
|
|
9641
9659
|
className: "fdc-field",
|
|
@@ -9649,9 +9667,9 @@ function ChatComposer({
|
|
|
9649
9667
|
disabled: !fileUploadHandler || disabled,
|
|
9650
9668
|
label: "Drop to attach",
|
|
9651
9669
|
hint: acceptFiles ? acceptFiles.replace(/,/g, " \xB7 ") : void 0,
|
|
9652
|
-
children: /* @__PURE__ */ (0,
|
|
9653
|
-
staged.items.length ? /* @__PURE__ */ (0,
|
|
9654
|
-
/* @__PURE__ */ (0,
|
|
9670
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)("div", { ref: wrap, className: "fdc-field-inner", children: [
|
|
9671
|
+
staged.items.length ? /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("div", { className: "fdc-staged", children: /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(FileStrip, { files: staged.items, size: narrow ? 60 : 68, onRemove: staged.remove, onRetry: staged.retry, onOpen: onOpenAttachment }) }) : null,
|
|
9672
|
+
/* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
|
|
9655
9673
|
MarkdownEditor,
|
|
9656
9674
|
{
|
|
9657
9675
|
ref: editor,
|
|
@@ -9670,33 +9688,33 @@ function ChatComposer({
|
|
|
9670
9688
|
ariaLabel: "Message"
|
|
9671
9689
|
}
|
|
9672
9690
|
),
|
|
9673
|
-
/* @__PURE__ */ (0,
|
|
9674
|
-
fileUploadHandler ? /* @__PURE__ */ (0,
|
|
9675
|
-
voiceHandler ? /* @__PURE__ */ (0,
|
|
9691
|
+
/* @__PURE__ */ (0, import_jsx_runtime75.jsxs)("div", { className: "fdc-tools", children: [
|
|
9692
|
+
fileUploadHandler ? /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(FilePickButton, { onFiles: staged.add, onReject: (r) => flash(r[0].message), accept: acceptFiles, maxFileSize, label: "Attach files", icon: "plus" }) : null,
|
|
9693
|
+
voiceHandler ? /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("button", { type: "button", className: "fd-attachbtn" + (listening ? " is-live" : ""), onClick: voice, "aria-pressed": listening, "aria-label": listening ? "Stop dictation" : "Dictate", children: /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("i", { className: "ph ph-" + (listening ? "waveform" : "microphone"), "aria-hidden": "true" }) }) : null,
|
|
9676
9694
|
toolbarExtras,
|
|
9677
|
-
/* @__PURE__ */ (0,
|
|
9678
|
-
maxLength && text.length > maxLength * 0.6 ? /* @__PURE__ */ (0,
|
|
9695
|
+
/* @__PURE__ */ (0, import_jsx_runtime75.jsx)("span", { className: "fdc-tools-gap" }),
|
|
9696
|
+
maxLength && text.length > maxLength * 0.6 ? /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)("span", { className: "fdc-count fd-tabular" + (text.length > maxLength * 0.95 ? " is-hot" : ""), children: [
|
|
9679
9697
|
text.length,
|
|
9680
9698
|
"/",
|
|
9681
9699
|
maxLength
|
|
9682
9700
|
] }) : null,
|
|
9683
|
-
busy ? /* @__PURE__ */ (0,
|
|
9684
|
-
/* @__PURE__ */ (0,
|
|
9685
|
-
/* @__PURE__ */ (0,
|
|
9686
|
-
] }) : /* @__PURE__ */ (0,
|
|
9687
|
-
/* @__PURE__ */ (0,
|
|
9688
|
-
/* @__PURE__ */ (0,
|
|
9701
|
+
busy ? /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)("button", { type: "button", className: "fdc-stop", onClick: onStop, "aria-label": "Stop generating", children: [
|
|
9702
|
+
/* @__PURE__ */ (0, import_jsx_runtime75.jsx)("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
|
|
9703
|
+
/* @__PURE__ */ (0, import_jsx_runtime75.jsx)("span", { children: "Stop" })
|
|
9704
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)("button", { type: "button", className: "fdc-send", onClick: submit, disabled: !canSend, "aria-label": "Send message", children: [
|
|
9705
|
+
/* @__PURE__ */ (0, import_jsx_runtime75.jsx)("i", { className: "ph ph-paper-plane-right", "aria-hidden": "true" }),
|
|
9706
|
+
/* @__PURE__ */ (0, import_jsx_runtime75.jsx)("span", { className: "fdc-send-label", children: "Send" })
|
|
9689
9707
|
] })
|
|
9690
9708
|
] })
|
|
9691
9709
|
] })
|
|
9692
9710
|
}
|
|
9693
9711
|
),
|
|
9694
|
-
notice ? /* @__PURE__ */ (0,
|
|
9695
|
-
/* @__PURE__ */ (0,
|
|
9712
|
+
notice ? /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)("div", { className: "fdc-notice", role: "status", children: [
|
|
9713
|
+
/* @__PURE__ */ (0, import_jsx_runtime75.jsx)("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
|
|
9696
9714
|
notice
|
|
9697
9715
|
] }) : null,
|
|
9698
|
-
hint && !notice ? /* @__PURE__ */ (0,
|
|
9699
|
-
/* @__PURE__ */ (0,
|
|
9716
|
+
hint && !notice ? /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("div", { className: "fdc-hint", children: hint }) : null,
|
|
9717
|
+
/* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
|
|
9700
9718
|
Popover,
|
|
9701
9719
|
{
|
|
9702
9720
|
open: menuOpen,
|
|
@@ -9710,12 +9728,12 @@ function ChatComposer({
|
|
|
9710
9728
|
returnFocus: false,
|
|
9711
9729
|
closeOnOutside: true,
|
|
9712
9730
|
label: trigger && trigger.type === "slash" ? "Commands" : "Mentions",
|
|
9713
|
-
children: /* @__PURE__ */ (0,
|
|
9731
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
|
|
9714
9732
|
Menu,
|
|
9715
9733
|
{
|
|
9716
9734
|
items: menuItems,
|
|
9717
9735
|
autoFocus: false,
|
|
9718
|
-
header: /* @__PURE__ */ (0,
|
|
9736
|
+
header: /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("div", { className: "fd-pop-group", children: trigger && trigger.type === "slash" ? "Commands" : "Attach context" }),
|
|
9719
9737
|
onClose: () => setTrigger(null)
|
|
9720
9738
|
}
|
|
9721
9739
|
)
|
|
@@ -9725,12 +9743,12 @@ function ChatComposer({
|
|
|
9725
9743
|
}
|
|
9726
9744
|
|
|
9727
9745
|
// src/components/chat/ChatSessionBar.tsx
|
|
9728
|
-
var
|
|
9729
|
-
var
|
|
9746
|
+
var React43 = __toESM(require("react"), 1);
|
|
9747
|
+
var import_jsx_runtime76 = require("react/jsx-runtime");
|
|
9730
9748
|
var compact2 = meterFormats.compact;
|
|
9731
9749
|
function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
|
|
9732
|
-
const [open, setOpen] =
|
|
9733
|
-
const anchor =
|
|
9750
|
+
const [open, setOpen] = React43.useState(false);
|
|
9751
|
+
const anchor = React43.useRef(null);
|
|
9734
9752
|
const stats = sessionStats || null;
|
|
9735
9753
|
const cu = contextUsage || null;
|
|
9736
9754
|
const limits = usageLimits || null;
|
|
@@ -9745,9 +9763,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
9745
9763
|
if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
|
|
9746
9764
|
if (cu) bits.push(pct + "% context");
|
|
9747
9765
|
const expandable = !!(cu || limits);
|
|
9748
|
-
return /* @__PURE__ */ (0,
|
|
9749
|
-
/* @__PURE__ */ (0,
|
|
9750
|
-
/* @__PURE__ */ (0,
|
|
9766
|
+
return /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(React43.Fragment, { children: [
|
|
9767
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fdc-bar", children: [
|
|
9768
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(
|
|
9751
9769
|
"button",
|
|
9752
9770
|
{
|
|
9753
9771
|
type: "button",
|
|
@@ -9758,16 +9776,16 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
9758
9776
|
"aria-expanded": expandable ? open : void 0,
|
|
9759
9777
|
"aria-label": expandable ? "Usage details" : void 0,
|
|
9760
9778
|
children: [
|
|
9761
|
-
cu ? /* @__PURE__ */ (0,
|
|
9762
|
-
/* @__PURE__ */ (0,
|
|
9763
|
-
expandable ? /* @__PURE__ */ (0,
|
|
9779
|
+
cu ? /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fdc-bar-mini", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(SegmentedMeter, { total, segments: cu.segments, height: 4, showTotal: false }) }) : null,
|
|
9780
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fdc-bar-text", children: bits.join(" \xB7 ") }),
|
|
9781
|
+
expandable ? /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("i", { className: "ph ph-caret-right fdc-bar-caret", "aria-hidden": "true" }) : null
|
|
9764
9782
|
]
|
|
9765
9783
|
}
|
|
9766
9784
|
),
|
|
9767
9785
|
extras
|
|
9768
9786
|
] }),
|
|
9769
|
-
/* @__PURE__ */ (0,
|
|
9770
|
-
cu ? /* @__PURE__ */ (0,
|
|
9787
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)(Popover, { open, anchorRef: anchor, placement: "top-start", onClose: () => setOpen(false), minWidth: 330, maxHeight: 460, padded: true, label: "Usage", children: /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "fdc-usage", children: [
|
|
9788
|
+
cu ? /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("section", { className: "fdc-usage-sec", children: /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
|
|
9771
9789
|
SegmentedMeter,
|
|
9772
9790
|
{
|
|
9773
9791
|
total,
|
|
@@ -9779,9 +9797,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
9779
9797
|
remainderLabel: "Free"
|
|
9780
9798
|
}
|
|
9781
9799
|
) }) : null,
|
|
9782
|
-
limits && limits.length ? /* @__PURE__ */ (0,
|
|
9783
|
-
/* @__PURE__ */ (0,
|
|
9784
|
-
/* @__PURE__ */ (0,
|
|
9800
|
+
limits && limits.length ? /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("section", { className: "fdc-usage-sec", children: [
|
|
9801
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("h4", { className: "fdc-usage-h", children: "Usage limits" }),
|
|
9802
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("div", { className: "fdc-usage-rows", children: limits.map((l) => /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
|
|
9785
9803
|
QuotaRow,
|
|
9786
9804
|
{
|
|
9787
9805
|
label: l.label,
|
|
@@ -9791,32 +9809,32 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
|
|
|
9791
9809
|
l.id
|
|
9792
9810
|
)) })
|
|
9793
9811
|
] }) : null,
|
|
9794
|
-
stats ? /* @__PURE__ */ (0,
|
|
9795
|
-
stats.elapsedMs ? /* @__PURE__ */ (0,
|
|
9796
|
-
/* @__PURE__ */ (0,
|
|
9797
|
-
/* @__PURE__ */ (0,
|
|
9812
|
+
stats ? /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("section", { className: "fdc-usage-sec fdc-usage-stats", children: [
|
|
9813
|
+
stats.elapsedMs ? /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { children: [
|
|
9814
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { children: "Session" }),
|
|
9815
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("b", { className: "fd-tabular", children: formatDuration(stats.elapsedMs) })
|
|
9798
9816
|
] }) : null,
|
|
9799
|
-
stats.tokens ? /* @__PURE__ */ (0,
|
|
9800
|
-
/* @__PURE__ */ (0,
|
|
9801
|
-
/* @__PURE__ */ (0,
|
|
9817
|
+
stats.tokens ? /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { children: [
|
|
9818
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { children: "Tokens" }),
|
|
9819
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("b", { className: "fd-tabular", children: stats.tokens.toLocaleString() })
|
|
9802
9820
|
] }) : null,
|
|
9803
|
-
stats.costUsd != null ? /* @__PURE__ */ (0,
|
|
9804
|
-
/* @__PURE__ */ (0,
|
|
9805
|
-
/* @__PURE__ */ (0,
|
|
9821
|
+
stats.costUsd != null ? /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { children: [
|
|
9822
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { children: "Cost" }),
|
|
9823
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("b", { className: "fd-tabular", children: [
|
|
9806
9824
|
"$",
|
|
9807
9825
|
Number(stats.costUsd).toFixed(3)
|
|
9808
9826
|
] })
|
|
9809
9827
|
] }) : null,
|
|
9810
|
-
stats.turns ? /* @__PURE__ */ (0,
|
|
9811
|
-
/* @__PURE__ */ (0,
|
|
9812
|
-
/* @__PURE__ */ (0,
|
|
9828
|
+
stats.turns ? /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { children: [
|
|
9829
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { children: "Turns" }),
|
|
9830
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("b", { className: "fd-tabular", children: stats.turns })
|
|
9813
9831
|
] }) : null
|
|
9814
9832
|
] }) : null,
|
|
9815
|
-
onClear ? /* @__PURE__ */ (0,
|
|
9833
|
+
onClear ? /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("footer", { className: "fdc-usage-foot", children: /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("button", { type: "button", className: "fdc-usage-clear", onClick: () => {
|
|
9816
9834
|
setOpen(false);
|
|
9817
9835
|
onClear();
|
|
9818
9836
|
}, children: [
|
|
9819
|
-
/* @__PURE__ */ (0,
|
|
9837
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("i", { className: "ph ph-trash", "aria-hidden": "true" }),
|
|
9820
9838
|
"Clear conversation"
|
|
9821
9839
|
] }) }) : null
|
|
9822
9840
|
] }) })
|
|
@@ -9853,7 +9871,7 @@ function ModelControls({
|
|
|
9853
9871
|
disabled: m.disabled,
|
|
9854
9872
|
checked: m.id === (current2 && current2.id),
|
|
9855
9873
|
meta: m.meta,
|
|
9856
|
-
shortcut: m.shortcut ? /* @__PURE__ */ (0,
|
|
9874
|
+
shortcut: m.shortcut ? /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(KeyHint, { keys: m.shortcut, size: "sm" }) : void 0,
|
|
9857
9875
|
onSelect: () => onModelChange && onModelChange(m.id)
|
|
9858
9876
|
});
|
|
9859
9877
|
const items = [{ kind: "section", label: "Models" }].concat(flat.map(item));
|
|
@@ -9866,15 +9884,15 @@ function ModelControls({
|
|
|
9866
9884
|
items.push({ kind: "section", label: "Fast mode" });
|
|
9867
9885
|
items.push({
|
|
9868
9886
|
kind: "custom",
|
|
9869
|
-
render: () => /* @__PURE__ */ (0,
|
|
9870
|
-
/* @__PURE__ */ (0,
|
|
9871
|
-
/* @__PURE__ */ (0,
|
|
9872
|
-
/* @__PURE__ */ (0,
|
|
9887
|
+
render: () => /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("label", { className: "fdc-switchrow", children: [
|
|
9888
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { children: fastModeLabel }),
|
|
9889
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("input", { type: "checkbox", className: "fd-sr", checked: !!fastMode, onChange: (e) => onFastModeChange(e.target.checked) }),
|
|
9890
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-switch-track" + (fastMode ? " is-on" : ""), "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fd-switch-thumb" }) })
|
|
9873
9891
|
] })
|
|
9874
9892
|
});
|
|
9875
9893
|
}
|
|
9876
|
-
return /* @__PURE__ */ (0,
|
|
9877
|
-
/* @__PURE__ */ (0,
|
|
9894
|
+
return /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(React43.Fragment, { children: [
|
|
9895
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
|
|
9878
9896
|
MenuButton,
|
|
9879
9897
|
{
|
|
9880
9898
|
items,
|
|
@@ -9885,7 +9903,7 @@ function ModelControls({
|
|
|
9885
9903
|
title: "Choose a model"
|
|
9886
9904
|
}
|
|
9887
9905
|
),
|
|
9888
|
-
effortLevels && effortLevels.length ? /* @__PURE__ */ (0,
|
|
9906
|
+
effortLevels && effortLevels.length ? /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
|
|
9889
9907
|
MenuButton,
|
|
9890
9908
|
{
|
|
9891
9909
|
placement: "top-end",
|
|
@@ -9906,7 +9924,7 @@ function ModelControls({
|
|
|
9906
9924
|
}
|
|
9907
9925
|
|
|
9908
9926
|
// src/components/chat/AgentChatPanel.tsx
|
|
9909
|
-
var
|
|
9927
|
+
var import_jsx_runtime77 = require("react/jsx-runtime");
|
|
9910
9928
|
var SURFACES = { sidebar: "is-sidebar", inline: "is-inline", page: "is-page", modal: "is-modal", sheet: "is-sheet" };
|
|
9911
9929
|
function AgentChatPanel({
|
|
9912
9930
|
/* required */
|
|
@@ -9990,11 +10008,11 @@ function AgentChatPanel({
|
|
|
9990
10008
|
onFeedback,
|
|
9991
10009
|
onEditMessage
|
|
9992
10010
|
}) {
|
|
9993
|
-
const [panelWidth, setPanelWidth] =
|
|
9994
|
-
const [applied, setApplied] =
|
|
9995
|
-
const [draft, setDraft] =
|
|
9996
|
-
const dragging =
|
|
9997
|
-
|
|
10011
|
+
const [panelWidth, setPanelWidth] = React44.useState(width);
|
|
10012
|
+
const [applied, setApplied] = React44.useState({});
|
|
10013
|
+
const [draft, setDraft] = React44.useState("");
|
|
10014
|
+
const dragging = React44.useRef(null);
|
|
10015
|
+
React44.useEffect(() => setPanelWidth(width), [width]);
|
|
9998
10016
|
const engine = useChatEngine({
|
|
9999
10017
|
contextType,
|
|
10000
10018
|
contextId,
|
|
@@ -10060,7 +10078,7 @@ function AgentChatPanel({
|
|
|
10060
10078
|
onReconnect: engine.reload,
|
|
10061
10079
|
deadTitle: "The assistant isn\u2019t reachable"
|
|
10062
10080
|
};
|
|
10063
|
-
const sessionBar = /* @__PURE__ */ (0,
|
|
10081
|
+
const sessionBar = /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
|
|
10064
10082
|
ChatSessionBar,
|
|
10065
10083
|
{
|
|
10066
10084
|
sessionStats,
|
|
@@ -10069,7 +10087,7 @@ function AgentChatPanel({
|
|
|
10069
10087
|
onClear: engine.visible.length ? engine.clear : void 0
|
|
10070
10088
|
}
|
|
10071
10089
|
);
|
|
10072
|
-
const modelControls = /* @__PURE__ */ (0,
|
|
10090
|
+
const modelControls = /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
|
|
10073
10091
|
ModelControls,
|
|
10074
10092
|
{
|
|
10075
10093
|
models,
|
|
@@ -10084,7 +10102,7 @@ function AgentChatPanel({
|
|
|
10084
10102
|
narrow
|
|
10085
10103
|
}
|
|
10086
10104
|
);
|
|
10087
|
-
const threadMenu = threads && threads.length ? /* @__PURE__ */ (0,
|
|
10105
|
+
const threadMenu = threads && threads.length ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
|
|
10088
10106
|
MenuButton,
|
|
10089
10107
|
{
|
|
10090
10108
|
variant: "ghost",
|
|
@@ -10111,7 +10129,7 @@ function AgentChatPanel({
|
|
|
10111
10129
|
})))
|
|
10112
10130
|
}
|
|
10113
10131
|
) : null;
|
|
10114
|
-
return /* @__PURE__ */ (0,
|
|
10132
|
+
return /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)(
|
|
10115
10133
|
"aside",
|
|
10116
10134
|
{
|
|
10117
10135
|
className: ["fdc-panel", SURFACES[surface] || SURFACES.sidebar, narrow ? "is-narrow" : "", className].filter(Boolean).join(" "),
|
|
@@ -10122,7 +10140,7 @@ function AgentChatPanel({
|
|
|
10122
10140
|
},
|
|
10123
10141
|
"aria-label": title,
|
|
10124
10142
|
children: [
|
|
10125
|
-
surface === "sidebar" && resizable ? /* @__PURE__ */ (0,
|
|
10143
|
+
surface === "sidebar" && resizable ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
|
|
10126
10144
|
"div",
|
|
10127
10145
|
{
|
|
10128
10146
|
className: "fdc-grip",
|
|
@@ -10137,20 +10155,20 @@ function AgentChatPanel({
|
|
|
10137
10155
|
}
|
|
10138
10156
|
}
|
|
10139
10157
|
) : null,
|
|
10140
|
-
showHeader ? /* @__PURE__ */ (0,
|
|
10141
|
-
/* @__PURE__ */ (0,
|
|
10142
|
-
/* @__PURE__ */ (0,
|
|
10143
|
-
/* @__PURE__ */ (0,
|
|
10144
|
-
subtitle ? /* @__PURE__ */ (0,
|
|
10158
|
+
showHeader ? /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("header", { className: "fdc-head", children: [
|
|
10159
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fdc-head-mark", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("i", { className: "ph ph-" + assistantIcon }) }),
|
|
10160
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("span", { className: "fdc-head-titles", children: [
|
|
10161
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fdc-head-title", children: title }),
|
|
10162
|
+
subtitle ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fdc-head-sub", children: subtitle }) : null
|
|
10145
10163
|
] }),
|
|
10146
|
-
/* @__PURE__ */ (0,
|
|
10164
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("span", { className: "fdc-head-acts", children: [
|
|
10147
10165
|
headerActions,
|
|
10148
10166
|
threadMenu,
|
|
10149
|
-
onNewThread ? /* @__PURE__ */ (0,
|
|
10150
|
-
onClose ? /* @__PURE__ */ (0,
|
|
10167
|
+
onNewThread ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("button", { type: "button", className: "fdc-iconbtn", onClick: onNewThread, "aria-label": "New conversation", title: "New conversation", children: /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("i", { className: "ph ph-plus", "aria-hidden": "true" }) }) : null,
|
|
10168
|
+
onClose ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("button", { type: "button", className: "fdc-iconbtn", onClick: onClose, "aria-label": "Close panel", title: "Close", children: /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
|
|
10151
10169
|
] })
|
|
10152
10170
|
] }) : null,
|
|
10153
|
-
/* @__PURE__ */ (0,
|
|
10171
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
|
|
10154
10172
|
ChatTranscript,
|
|
10155
10173
|
{
|
|
10156
10174
|
messages: engine.visible,
|
|
@@ -10165,7 +10183,7 @@ function AgentChatPanel({
|
|
|
10165
10183
|
renderEmpty
|
|
10166
10184
|
}
|
|
10167
10185
|
),
|
|
10168
|
-
/* @__PURE__ */ (0,
|
|
10186
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
|
|
10169
10187
|
ChatComposer,
|
|
10170
10188
|
{
|
|
10171
10189
|
onSubmit: (text, atts) => engine.send(text, atts),
|
|
@@ -10198,7 +10216,7 @@ function AgentChatPanel({
|
|
|
10198
10216
|
}
|
|
10199
10217
|
|
|
10200
10218
|
// src/kits/query.ts
|
|
10201
|
-
var
|
|
10219
|
+
var React45 = __toESM(require("react"), 1);
|
|
10202
10220
|
function eqFilter(get2) {
|
|
10203
10221
|
return (row, value) => Array.isArray(value) ? value.includes(get2(row)) : get2(row) === value;
|
|
10204
10222
|
}
|
|
@@ -10230,22 +10248,22 @@ function compare(a, b, dir) {
|
|
|
10230
10248
|
var API = null;
|
|
10231
10249
|
var PREFS = null;
|
|
10232
10250
|
function useServerTable({ endpoint, params, defaults, deps, prefsKey }) {
|
|
10233
|
-
const [query, setQuery] =
|
|
10251
|
+
const [query, setQuery] = React45.useState(() => {
|
|
10234
10252
|
const store = PREFS || window.PlannerPrefs;
|
|
10235
10253
|
const saved = prefsKey && store ? store.getTable(prefsKey) : {};
|
|
10236
10254
|
return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
|
|
10237
10255
|
});
|
|
10238
|
-
const savePref =
|
|
10256
|
+
const savePref = React45.useCallback((patch2) => {
|
|
10239
10257
|
const store = PREFS || window.PlannerPrefs;
|
|
10240
10258
|
if (prefsKey && store) store.setTable(prefsKey, patch2);
|
|
10241
10259
|
}, [prefsKey]);
|
|
10242
|
-
const [res, setRes] =
|
|
10243
|
-
const [loading, setLoading] =
|
|
10244
|
-
const seq2 =
|
|
10260
|
+
const [res, setRes] = React45.useState(null);
|
|
10261
|
+
const [loading, setLoading] = React45.useState(true);
|
|
10262
|
+
const seq2 = React45.useRef(0);
|
|
10245
10263
|
const depKey = (deps || []).join("|");
|
|
10246
10264
|
const paramKey = JSON.stringify(params || {});
|
|
10247
10265
|
const queryKey = JSON.stringify(query);
|
|
10248
|
-
|
|
10266
|
+
React45.useEffect(() => {
|
|
10249
10267
|
const id = ++seq2.current;
|
|
10250
10268
|
setLoading(true);
|
|
10251
10269
|
const t = setTimeout(() => {
|