@ai-matrx/records-ui 0.53.0 → 0.57.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/CHANGELOG.md +117 -0
- package/dist/index.cjs +331 -198
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +19 -1
- package/dist/index.d.ts +19 -1
- package/dist/index.js +331 -198
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -2539,7 +2539,7 @@ function EnrichPanel({ tableId, fieldId, className }) {
|
|
|
2539
2539
|
import { useState as useState8 } from "react";
|
|
2540
2540
|
import { Badge as Badge4, Button as Button6, Separator } from "@ai-matrx/design-system";
|
|
2541
2541
|
import { Fragment as Fragment4, jsx as jsx11, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
2542
|
-
function PastePreview({ plan, noun, onConfirm, onCancel }) {
|
|
2542
|
+
function PastePreview({ plan, noun, nounPlural, onConfirm, onCancel }) {
|
|
2543
2543
|
const [busy, setBusy] = useState8(false);
|
|
2544
2544
|
const [outcome, setOutcome] = useState8(null);
|
|
2545
2545
|
const nothingToDo = plan.cells === 0;
|
|
@@ -2559,7 +2559,7 @@ function PastePreview({ plan, noun, onConfirm, onCancel }) {
|
|
|
2559
2559
|
/* @__PURE__ */ jsx11(Separator, {}),
|
|
2560
2560
|
outcome === null ? /* @__PURE__ */ jsxs7(Fragment4, { children: [
|
|
2561
2561
|
nothingToDo ? /* @__PURE__ */ jsx11("p", { className: "text-sm", children: "Nothing in what you pasted can be written to this table. Every cell is listed below with the reason." }) : /* @__PURE__ */ jsxs7("p", { className: "text-sm", children: [
|
|
2562
|
-
sentence(plan, noun),
|
|
2562
|
+
sentence(plan, noun, nounPlural),
|
|
2563
2563
|
" The values below are exactly what will be stored."
|
|
2564
2564
|
] }),
|
|
2565
2565
|
/* @__PURE__ */ jsx11(PlanTable, { plan }),
|
|
@@ -2599,7 +2599,7 @@ function PastePreview({ plan, noun, onConfirm, onCancel }) {
|
|
|
2599
2599
|
setBusy(true);
|
|
2600
2600
|
void onConfirm().then(setOutcome).finally(() => setBusy(false));
|
|
2601
2601
|
},
|
|
2602
|
-
children: busy ? "Writing\u2026" : confirmLabel(plan, noun)
|
|
2602
|
+
children: busy ? "Writing\u2026" : confirmLabel(plan, noun, nounPlural)
|
|
2603
2603
|
}
|
|
2604
2604
|
)
|
|
2605
2605
|
] })
|
|
@@ -2654,19 +2654,19 @@ function plural(n, one, many) {
|
|
|
2654
2654
|
function summarize(plan) {
|
|
2655
2655
|
return `${plural(plan.cells, "value", "values")} across ${plural(plan.rows.length, "row", "rows")}`;
|
|
2656
2656
|
}
|
|
2657
|
-
function sentence(plan, noun) {
|
|
2657
|
+
function sentence(plan, noun, nounPlural) {
|
|
2658
2658
|
const parts = [];
|
|
2659
|
-
if (plan.updates > 0) parts.push(`change ${plural(plan.updates, noun,
|
|
2660
|
-
if (plan.creates > 0) parts.push(`create ${plural(plan.creates, `new ${noun}`, `new ${
|
|
2659
|
+
if (plan.updates > 0) parts.push(`change ${plural(plan.updates, noun, nounPlural)}`);
|
|
2660
|
+
if (plan.creates > 0) parts.push(`create ${plural(plan.creates, `new ${noun}`, `new ${nounPlural}`)}`);
|
|
2661
2661
|
const what = parts.length === 2 ? `${parts[0]} and ${parts[1]}` : parts[0] ?? "write nothing";
|
|
2662
2662
|
return `This will ${what}.`;
|
|
2663
2663
|
}
|
|
2664
|
-
function confirmLabel(plan, noun) {
|
|
2664
|
+
function confirmLabel(plan, noun, nounPlural) {
|
|
2665
2665
|
if (plan.creates > 0 && plan.updates === 0) {
|
|
2666
|
-
return `Create ${plural(plan.creates, noun,
|
|
2666
|
+
return `Create ${plural(plan.creates, noun, nounPlural)}`;
|
|
2667
2667
|
}
|
|
2668
2668
|
if (plan.creates > 0) return `Write ${plural(plan.rows.length, "row", "rows")}`;
|
|
2669
|
-
return `Update ${plural(plan.updates, noun,
|
|
2669
|
+
return `Update ${plural(plan.updates, noun, nounPlural)}`;
|
|
2670
2670
|
}
|
|
2671
2671
|
|
|
2672
2672
|
// src/pasteValues.ts
|
|
@@ -2701,13 +2701,21 @@ function valueFromPastedText(field, raw) {
|
|
|
2701
2701
|
return { value: negative ? -n : n };
|
|
2702
2702
|
}
|
|
2703
2703
|
case "datetime": {
|
|
2704
|
+
const wantsTime = String(field.config?.["kind"] ?? "date") === "datetime";
|
|
2705
|
+
const plainDay = /^\s*(\d{4})-(\d{2})-(\d{2})\s*$/.exec(raw);
|
|
2706
|
+
if (!wantsTime && plainDay) return { value: `${plainDay[1]}-${plainDay[2]}-${plainDay[3]}` };
|
|
2704
2707
|
const at = Date.parse(text);
|
|
2705
2708
|
if (Number.isNaN(at)) {
|
|
2706
2709
|
return {
|
|
2707
2710
|
refusal: `${label} holds a date, and \u201C${raw}\u201D is not one this can read. Paste it as 2026-09-21, or as your spreadsheet's own date format.`
|
|
2708
2711
|
};
|
|
2709
2712
|
}
|
|
2710
|
-
|
|
2713
|
+
const parsed = new Date(at);
|
|
2714
|
+
if (wantsTime) return { value: parsed.toISOString() };
|
|
2715
|
+
const y = parsed.getFullYear();
|
|
2716
|
+
const m = String(parsed.getMonth() + 1).padStart(2, "0");
|
|
2717
|
+
const d = String(parsed.getDate()).padStart(2, "0");
|
|
2718
|
+
return { value: `${y}-${m}-${d}` };
|
|
2711
2719
|
}
|
|
2712
2720
|
case "json": {
|
|
2713
2721
|
try {
|
|
@@ -2898,42 +2906,55 @@ function Grid({
|
|
|
2898
2906
|
const fieldList = fields.data ?? [];
|
|
2899
2907
|
const byRecord = /* @__PURE__ */ new Map();
|
|
2900
2908
|
const order = [];
|
|
2901
|
-
|
|
2902
|
-
let held = byRecord.get(
|
|
2909
|
+
const take = (rowId, columnId, value) => {
|
|
2910
|
+
let held = byRecord.get(rowId);
|
|
2903
2911
|
if (held === void 0) {
|
|
2904
2912
|
held = {};
|
|
2905
|
-
byRecord.set(
|
|
2906
|
-
order.push(
|
|
2913
|
+
byRecord.set(rowId, held);
|
|
2914
|
+
order.push(rowId);
|
|
2907
2915
|
}
|
|
2908
|
-
held[
|
|
2916
|
+
held[columnId] = value === null || value === void 0 ? "" : String(value);
|
|
2917
|
+
};
|
|
2918
|
+
for (const patch of sheetPlan.accepted) take(patch.rowId, patch.columnId, patch.value);
|
|
2919
|
+
for (const refused of sheetPlan.refusals) {
|
|
2920
|
+
if (refused.rowId === null) continue;
|
|
2921
|
+
take(refused.rowId, refused.columnId, refused.value);
|
|
2909
2922
|
}
|
|
2923
|
+
const onScreen = rows.map((r) => r.id).filter((id) => byRecord.has(id));
|
|
2924
|
+
const touched = [...onScreen, ...order.filter((id) => !onScreen.includes(id))];
|
|
2910
2925
|
const columnKeys = Array.from(
|
|
2911
2926
|
/* @__PURE__ */ new Set([
|
|
2912
2927
|
...sheetPlan.accepted.map((p) => p.columnId),
|
|
2928
|
+
...sheetPlan.refusals.map((r) => r.columnId),
|
|
2913
2929
|
...sheetPlan.overflow.flatMap((row) => Object.keys(row))
|
|
2914
2930
|
])
|
|
2915
2931
|
);
|
|
2916
2932
|
const built = planPastedBlock({
|
|
2917
2933
|
fields: fieldList,
|
|
2918
2934
|
columnKeys,
|
|
2919
|
-
onExisting:
|
|
2935
|
+
onExisting: touched.map((recordId) => ({
|
|
2920
2936
|
recordId,
|
|
2921
2937
|
raw: columnKeys.map((key) => byRecord.get(recordId)?.[key])
|
|
2922
2938
|
})),
|
|
2923
2939
|
onNew: sheetPlan.overflow.map((row) => columnKeys.map((key) => row[key])),
|
|
2924
2940
|
pastRightEdge: sheetPlan.pastRightEdge
|
|
2925
2941
|
});
|
|
2942
|
+
const notWritable = /* @__PURE__ */ new Map();
|
|
2926
2943
|
for (const refused of sheetPlan.refusals) {
|
|
2944
|
+
if (built.refusals.some((r) => r.column === columnLabel(fieldList, refused.columnId))) continue;
|
|
2945
|
+
notWritable.set(refused.columnId, refused.reason);
|
|
2946
|
+
}
|
|
2947
|
+
for (const [columnId, why] of notWritable) {
|
|
2927
2948
|
built.refusals.push({
|
|
2928
2949
|
fromLine: 0,
|
|
2929
|
-
column:
|
|
2950
|
+
column: columnLabel(fieldList, columnId),
|
|
2930
2951
|
raw: "",
|
|
2931
|
-
why
|
|
2952
|
+
why
|
|
2932
2953
|
});
|
|
2933
2954
|
}
|
|
2934
2955
|
setPastePlan({ plan: built });
|
|
2935
2956
|
},
|
|
2936
|
-
[fields.data]
|
|
2957
|
+
[fields.data, rows]
|
|
2937
2958
|
);
|
|
2938
2959
|
const applyPaste = useCallback6(async () => {
|
|
2939
2960
|
const held = pastePlan;
|
|
@@ -3244,6 +3265,7 @@ function Grid({
|
|
|
3244
3265
|
{
|
|
3245
3266
|
plan: pastePlan.plan,
|
|
3246
3267
|
noun: table.data?.label_singular ?? "record",
|
|
3268
|
+
nounPlural: table.data?.label_plural ?? `${table.data?.label_singular ?? "record"}s`,
|
|
3247
3269
|
onConfirm: applyPaste,
|
|
3248
3270
|
onCancel: () => setPastePlan(null)
|
|
3249
3271
|
}
|
|
@@ -3261,6 +3283,10 @@ function Grid({
|
|
|
3261
3283
|
] })
|
|
3262
3284
|
] }) });
|
|
3263
3285
|
}
|
|
3286
|
+
function columnLabel(fields, columnId) {
|
|
3287
|
+
const field = fields.find((f) => f.key === columnId);
|
|
3288
|
+
return field ? fieldName(field) : humanize(columnId);
|
|
3289
|
+
}
|
|
3264
3290
|
function AddFieldButton({ onClick }) {
|
|
3265
3291
|
return /* @__PURE__ */ jsx12(
|
|
3266
3292
|
Button7,
|
|
@@ -4621,6 +4647,60 @@ var CONDITION_OPS = [
|
|
|
4621
4647
|
{ op: "gt", label: "is more than" },
|
|
4622
4648
|
{ op: "lt", label: "is less than" }
|
|
4623
4649
|
];
|
|
4650
|
+
function conditionIsSimple(expr) {
|
|
4651
|
+
if (expr === null || expr === void 0) return true;
|
|
4652
|
+
const node = expr;
|
|
4653
|
+
if (typeof node.op !== "string" || !CONDITION_OPS.some((c) => c.op === node.op)) return false;
|
|
4654
|
+
if (!Array.isArray(node.args)) return false;
|
|
4655
|
+
const first = node.args[0];
|
|
4656
|
+
if (!first || typeof first.field !== "string") return false;
|
|
4657
|
+
if (node.op === "present") return node.args.length === 1;
|
|
4658
|
+
const second = node.args[1];
|
|
4659
|
+
return node.args.length === 2 && !!second && "const" in second;
|
|
4660
|
+
}
|
|
4661
|
+
function conditionInWords(expr, fields) {
|
|
4662
|
+
const name = (id) => {
|
|
4663
|
+
const f = fields.find((x) => x.id === id);
|
|
4664
|
+
return f ? f.label || f.key : "a column";
|
|
4665
|
+
};
|
|
4666
|
+
const said = {
|
|
4667
|
+
eq: "is",
|
|
4668
|
+
ne: "is not",
|
|
4669
|
+
gt: "is more than",
|
|
4670
|
+
lt: "is less than",
|
|
4671
|
+
gte: "is at least",
|
|
4672
|
+
lte: "is at most",
|
|
4673
|
+
and: "and",
|
|
4674
|
+
or: "or",
|
|
4675
|
+
matches: "matches"
|
|
4676
|
+
};
|
|
4677
|
+
const walk = (node) => {
|
|
4678
|
+
if (node === null || node === void 0) return "nothing";
|
|
4679
|
+
const n = node;
|
|
4680
|
+
if ("const" in n) return JSON.stringify(n["const"]);
|
|
4681
|
+
if (typeof n["field"] === "string" && !("op" in n)) return name(n["field"]);
|
|
4682
|
+
const op = typeof n["op"] === "string" ? n["op"] : "";
|
|
4683
|
+
if (op === "previous" && typeof n["field"] === "string") return `what ${name(n["field"])} used to say`;
|
|
4684
|
+
if (op === "sibling_count") {
|
|
4685
|
+
const same = n["same"] ?? [];
|
|
4686
|
+
const differs = n["differs"] ?? [];
|
|
4687
|
+
const sameWords = same.length > 0 ? ` for the same ${same.map(name).join(" and ")}` : "";
|
|
4688
|
+
const diffWords = differs.length > 0 ? ` from a different ${differs.map(name).join(" and ")}` : "";
|
|
4689
|
+
return `how many others there are${sameWords}${diffWords}`;
|
|
4690
|
+
}
|
|
4691
|
+
if (op === "stage_count") return "how many are in that column already";
|
|
4692
|
+
if (op === "actor_at_least") return `whoever is moving it is at least ${String(n["level"] ?? "somebody")}`;
|
|
4693
|
+
const args = Array.isArray(n["args"]) ? n["args"] : [];
|
|
4694
|
+
if (op === "not") return `not ${walk(args[0])}`;
|
|
4695
|
+
if (op === "present") return `${walk(args[0])} has been answered`;
|
|
4696
|
+
const word = said[op] ?? op;
|
|
4697
|
+
if (op === "and" || op === "or") return args.map(walk).join(` ${word} `);
|
|
4698
|
+
if (args.length === 2) return `${walk(args[0])} ${word} ${walk(args[1])}`;
|
|
4699
|
+
if (args.length === 1) return `${walk(args[0])} ${word}`;
|
|
4700
|
+
return op;
|
|
4701
|
+
};
|
|
4702
|
+
return walk(expr);
|
|
4703
|
+
}
|
|
4624
4704
|
function conditionValue(typed) {
|
|
4625
4705
|
const trimmed = typed.trim();
|
|
4626
4706
|
if (trimmed === "") return typed;
|
|
@@ -4692,6 +4772,7 @@ function ConditionRow({ lead, expr, fields, onChange, emptyLabel = "always", cla
|
|
|
4692
4772
|
import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
4693
4773
|
var NO_RULES_YET = "Nothing has to be true to get here yet.";
|
|
4694
4774
|
var NEEDS_A_SENTENCE = "Write the sentence somebody reads when this stops them, the way you would say it out loud.";
|
|
4775
|
+
var NOT_DRAWN_HERE = "This part of the rule is not something this builder can draw yet";
|
|
4695
4776
|
var ON_FAIL = [
|
|
4696
4777
|
{ value: "refuse", label: "Turn it away", note: "The card stays where it is and the person is told why." },
|
|
4697
4778
|
{
|
|
@@ -4872,7 +4953,7 @@ function StageRulesSection({ tableId, stage, className }) {
|
|
|
4872
4953
|
}
|
|
4873
4954
|
),
|
|
4874
4955
|
/* @__PURE__ */ jsx18(
|
|
4875
|
-
|
|
4956
|
+
Clause,
|
|
4876
4957
|
{
|
|
4877
4958
|
lead: "When",
|
|
4878
4959
|
emptyLabel: "every card",
|
|
@@ -4882,7 +4963,7 @@ function StageRulesSection({ tableId, stage, className }) {
|
|
|
4882
4963
|
}
|
|
4883
4964
|
),
|
|
4884
4965
|
/* @__PURE__ */ jsx18(
|
|
4885
|
-
|
|
4966
|
+
Clause,
|
|
4886
4967
|
{
|
|
4887
4968
|
lead: "it cannot get here unless",
|
|
4888
4969
|
emptyLabel: "\u2014 pick a column \u2014",
|
|
@@ -4926,6 +5007,50 @@ function StageRulesSection({ tableId, stage, className }) {
|
|
|
4926
5007
|
/* @__PURE__ */ jsx18(Separator5, {})
|
|
4927
5008
|
] });
|
|
4928
5009
|
}
|
|
5010
|
+
function Clause({
|
|
5011
|
+
lead,
|
|
5012
|
+
emptyLabel,
|
|
5013
|
+
expr,
|
|
5014
|
+
fields,
|
|
5015
|
+
onChange
|
|
5016
|
+
}) {
|
|
5017
|
+
const [replacing, setReplacing] = useState14(false);
|
|
5018
|
+
const drawable = conditionIsSimple(expr) || replacing;
|
|
5019
|
+
if (drawable) {
|
|
5020
|
+
return /* @__PURE__ */ jsx18(
|
|
5021
|
+
ConditionRow,
|
|
5022
|
+
{
|
|
5023
|
+
lead,
|
|
5024
|
+
emptyLabel,
|
|
5025
|
+
expr: replacing && !conditionIsSimple(expr) ? null : expr,
|
|
5026
|
+
fields,
|
|
5027
|
+
onChange
|
|
5028
|
+
}
|
|
5029
|
+
);
|
|
5030
|
+
}
|
|
5031
|
+
return /* @__PURE__ */ jsxs14("div", { className: "flex flex-wrap items-center gap-1 text-xs", "data-testid": "stage-rule-clause-in-words", children: [
|
|
5032
|
+
/* @__PURE__ */ jsx18("span", { className: "text-muted-foreground", children: lead }),
|
|
5033
|
+
/* @__PURE__ */ jsx18("span", { className: "font-medium", children: conditionInWords(expr, fields) }),
|
|
5034
|
+
/* @__PURE__ */ jsxs14("span", { className: "text-muted-foreground", children: [
|
|
5035
|
+
"\u2014 ",
|
|
5036
|
+
NOT_DRAWN_HERE,
|
|
5037
|
+
", so it is shown as it reads."
|
|
5038
|
+
] }),
|
|
5039
|
+
/* @__PURE__ */ jsx18(
|
|
5040
|
+
Button12,
|
|
5041
|
+
{
|
|
5042
|
+
size: "sm",
|
|
5043
|
+
variant: "ghost",
|
|
5044
|
+
className: "h-6",
|
|
5045
|
+
onClick: () => {
|
|
5046
|
+
setReplacing(true);
|
|
5047
|
+
onChange(null);
|
|
5048
|
+
},
|
|
5049
|
+
children: "Replace it"
|
|
5050
|
+
}
|
|
5051
|
+
)
|
|
5052
|
+
] });
|
|
5053
|
+
}
|
|
4929
5054
|
|
|
4930
5055
|
// src/TableSettings.tsx
|
|
4931
5056
|
import { useState as useState15 } from "react";
|
|
@@ -8685,7 +8810,7 @@ function PortalBuilder({ tableId, portalId, onSaved, onClose, className }) {
|
|
|
8685
8810
|
const all = tables.data ?? [];
|
|
8686
8811
|
const missingTie = ticked.filter((e) => e.namesVia.trim() === "");
|
|
8687
8812
|
const ready = clientTableId !== null && ticked.length > 0 && missingTie.length === 0;
|
|
8688
|
-
return /* @__PURE__ */ jsxs29("section", { className: cn27("flex flex-col gap-3", className), children: [
|
|
8813
|
+
return /* @__PURE__ */ jsxs29("section", { className: cn27("@container flex flex-col gap-3", className), children: [
|
|
8689
8814
|
/* @__PURE__ */ jsxs29("header", { className: "flex items-center gap-2", children: [
|
|
8690
8815
|
/* @__PURE__ */ jsx33("h3", { className: "text-sm font-medium", children: existing ? "Portal" : "New client portal" }),
|
|
8691
8816
|
/* @__PURE__ */ jsx33("div", { className: "flex-1" }),
|
|
@@ -8826,7 +8951,7 @@ function PortalBuilder({ tableId, portalId, onSaved, onClose, className }) {
|
|
|
8826
8951
|
/* @__PURE__ */ jsx33(
|
|
8827
8952
|
BasicInput8,
|
|
8828
8953
|
{
|
|
8829
|
-
className: "h-8 w-56",
|
|
8954
|
+
className: "h-8 w-full @md:w-56",
|
|
8830
8955
|
value: inviteEmail,
|
|
8831
8956
|
onChange: (e) => setInviteEmail(e.target.value)
|
|
8832
8957
|
}
|
|
@@ -8837,7 +8962,7 @@ function PortalBuilder({ tableId, portalId, onSaved, onClose, className }) {
|
|
|
8837
8962
|
/* @__PURE__ */ jsx33(
|
|
8838
8963
|
BasicInput8,
|
|
8839
8964
|
{
|
|
8840
|
-
className: "h-8 w-80",
|
|
8965
|
+
className: "h-8 w-full @md:w-80",
|
|
8841
8966
|
placeholder: "the record id",
|
|
8842
8967
|
value: inviteRecordId,
|
|
8843
8968
|
onChange: (e) => setInviteRecordId(e.target.value)
|
|
@@ -9536,7 +9661,7 @@ function DigestScheduler({
|
|
|
9536
9661
|
setPreview(answered.data);
|
|
9537
9662
|
}
|
|
9538
9663
|
if (views === null && !error) return /* @__PURE__ */ jsx36(Skeleton16, { className: cn30("h-56 w-full", className) });
|
|
9539
|
-
return /* @__PURE__ */ jsxs32("section", { className: cn30("flex flex-col gap-3", className), children: [
|
|
9664
|
+
return /* @__PURE__ */ jsxs32("section", { className: cn30("@container flex flex-col gap-3", className), children: [
|
|
9540
9665
|
/* @__PURE__ */ jsxs32("header", { className: "flex items-center gap-2", children: [
|
|
9541
9666
|
/* @__PURE__ */ jsx36("h3", { className: "text-sm font-medium", children: "Send this on a schedule" }),
|
|
9542
9667
|
/* @__PURE__ */ jsx36("div", { className: "flex-1" }),
|
|
@@ -9571,7 +9696,7 @@ function DigestScheduler({
|
|
|
9571
9696
|
),
|
|
9572
9697
|
/* @__PURE__ */ jsx36("span", { className: "text-xs text-muted-foreground", children: "The first choice saves what is on screen as a view, so the summary and the screen stay the same thing." })
|
|
9573
9698
|
] }),
|
|
9574
|
-
/* @__PURE__ */ jsxs32("div", { className: "grid grid-cols-
|
|
9699
|
+
/* @__PURE__ */ jsxs32("div", { className: "grid grid-cols-1 gap-2 @md:grid-cols-2", children: [
|
|
9575
9700
|
/* @__PURE__ */ jsxs32("label", { className: "flex flex-col gap-1", children: [
|
|
9576
9701
|
/* @__PURE__ */ jsx36(Label5, { className: "text-xs font-medium", children: "How often" }),
|
|
9577
9702
|
/* @__PURE__ */ jsx36(
|
|
@@ -10320,7 +10445,7 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
|
|
|
10320
10445
|
if (!rights.admin) {
|
|
10321
10446
|
return /* @__PURE__ */ jsx39("p", { className: cn33("text-xs text-muted-foreground", className), children: rights.why("structure") });
|
|
10322
10447
|
}
|
|
10323
|
-
return /* @__PURE__ */ jsxs35("div", { className: cn33("flex min-h-0 gap-3", className), children: [
|
|
10448
|
+
return /* @__PURE__ */ jsxs35("div", { className: cn33("@container flex min-h-0 flex-col gap-3 @3xl:flex-row", className), children: [
|
|
10324
10449
|
/* @__PURE__ */ jsxs35("div", { className: "flex min-w-0 flex-1 flex-col gap-2 overflow-auto", children: [
|
|
10325
10450
|
/* @__PURE__ */ jsxs35("div", { className: "flex items-center gap-1 overflow-x-auto", role: "group", "aria-label": "Forms", children: [
|
|
10326
10451
|
forms.map((form) => /* @__PURE__ */ jsx39(
|
|
@@ -10481,7 +10606,7 @@ function FormBuilder({ tableId, seed, activeFormId, onActiveForm, className }) {
|
|
|
10481
10606
|
] })
|
|
10482
10607
|
] })
|
|
10483
10608
|
] }),
|
|
10484
|
-
draft ? /* @__PURE__ */ jsxs35("aside", { className: "w-
|
|
10609
|
+
draft ? /* @__PURE__ */ jsxs35("aside", { className: "w-full shrink-0 overflow-auto rounded border p-2 @3xl:w-96", children: [
|
|
10485
10610
|
/* @__PURE__ */ jsx39("h4", { className: "px-1 text-sm font-medium", children: draft.name }),
|
|
10486
10611
|
/* @__PURE__ */ jsx39(FormRunner, { form: draft, preview: true })
|
|
10487
10612
|
] }) : null
|
|
@@ -12269,195 +12394,200 @@ function BookingBuilder({ tableId, bookingId, onSaved, onClose, className }) {
|
|
|
12269
12394
|
}
|
|
12270
12395
|
const url = formId ? `${publicOrigin}${bookingPath(formId)}` : null;
|
|
12271
12396
|
const shown = offer ?? null;
|
|
12272
|
-
return
|
|
12273
|
-
|
|
12274
|
-
|
|
12275
|
-
|
|
12276
|
-
|
|
12277
|
-
|
|
12278
|
-
|
|
12279
|
-
|
|
12280
|
-
|
|
12281
|
-
|
|
12282
|
-
/* @__PURE__ */ jsx48(BasicInput15, { value: title, onChange: (e) => setTitle(e.target.value) })
|
|
12283
|
-
] }),
|
|
12284
|
-
/* @__PURE__ */ jsxs44("div", { className: "grid grid-cols-2 gap-2", children: [
|
|
12285
|
-
/* @__PURE__ */ jsxs44("label", { className: "flex flex-col gap-1", children: [
|
|
12286
|
-
/* @__PURE__ */ jsx48(Label8, { className: "text-xs font-medium", children: "How long one appointment is" }),
|
|
12287
|
-
/* @__PURE__ */ jsx48(
|
|
12288
|
-
"select",
|
|
12289
|
-
{
|
|
12290
|
-
className: "h-9 rounded border bg-background px-2 text-sm",
|
|
12291
|
-
value: minutes,
|
|
12292
|
-
onChange: (e) => setMinutes(Number(e.target.value)),
|
|
12293
|
-
children: LENGTHS.map((n) => /* @__PURE__ */ jsxs44("option", { value: n, children: [
|
|
12294
|
-
n,
|
|
12295
|
-
" minutes"
|
|
12296
|
-
] }, n))
|
|
12297
|
-
}
|
|
12298
|
-
)
|
|
12299
|
-
] }),
|
|
12300
|
-
/* @__PURE__ */ jsxs44("label", { className: "flex flex-col gap-1", children: [
|
|
12301
|
-
/* @__PURE__ */ jsx48(Label8, { className: "text-xs font-medium", children: "Gap kept after each one" }),
|
|
12302
|
-
/* @__PURE__ */ jsx48(
|
|
12303
|
-
"select",
|
|
12304
|
-
{
|
|
12305
|
-
className: "h-9 rounded border bg-background px-2 text-sm",
|
|
12306
|
-
value: buffer,
|
|
12307
|
-
onChange: (e) => setBuffer(Number(e.target.value)),
|
|
12308
|
-
children: [0, 5, 10, 15, 30].map((n) => /* @__PURE__ */ jsx48("option", { value: n, children: n === 0 ? "No gap \u2014 back to back" : `${n} minutes` }, n))
|
|
12309
|
-
}
|
|
12310
|
-
)
|
|
12311
|
-
] }),
|
|
12312
|
-
/* @__PURE__ */ jsxs44("label", { className: "flex flex-col gap-1", children: [
|
|
12313
|
-
/* @__PURE__ */ jsx48(Label8, { className: "text-xs font-medium", children: "Earliest somebody may book" }),
|
|
12314
|
-
/* @__PURE__ */ jsx48(
|
|
12315
|
-
"select",
|
|
12316
|
-
{
|
|
12317
|
-
className: "h-9 rounded border bg-background px-2 text-sm",
|
|
12318
|
-
value: lead,
|
|
12319
|
-
onChange: (e) => setLead(Number(e.target.value)),
|
|
12320
|
-
children: [0, 60, 120, 240, 1440].map((n) => /* @__PURE__ */ jsx48("option", { value: n, children: n === 0 ? "Right away" : n === 1440 ? "A day from now" : `${n / 60} hour${n === 60 ? "" : "s"} from now` }, n))
|
|
12321
|
-
}
|
|
12322
|
-
)
|
|
12397
|
+
return (
|
|
12398
|
+
// THE RAIL IS 384px WIDE AND THE VIEWPORT IS NOT (walk 1, 2026-09-21):
|
|
12399
|
+
// every split below is a CONTAINER query, so this screen is the same
|
|
12400
|
+
// screen in a rail, a dialog and a full page.
|
|
12401
|
+
/* @__PURE__ */ jsxs44("section", { className: cn42("@container flex flex-col gap-3", className), children: [
|
|
12402
|
+
/* @__PURE__ */ jsxs44("header", { className: "flex items-center gap-2", children: [
|
|
12403
|
+
/* @__PURE__ */ jsx48("h3", { className: "text-sm font-medium", children: existing ? "Booking page" : "New booking page" }),
|
|
12404
|
+
/* @__PURE__ */ jsx48("div", { className: "flex-1" }),
|
|
12405
|
+
/* @__PURE__ */ jsx48(Button39, { size: "sm", disabled: saving, onClick: () => void save(), children: saving ? "Saving\u2026" : "Save" }),
|
|
12406
|
+
onClose ? /* @__PURE__ */ jsx48(Button39, { size: "sm", variant: "ghost", onClick: onClose, children: "Close" }) : null
|
|
12323
12407
|
] }),
|
|
12408
|
+
error ? /* @__PURE__ */ jsx48(RefusalNotice, { error }) : null,
|
|
12324
12409
|
/* @__PURE__ */ jsxs44("label", { className: "flex flex-col gap-1", children: [
|
|
12325
|
-
/* @__PURE__ */ jsx48(Label8, { className: "text-xs font-medium", children: "
|
|
12326
|
-
/* @__PURE__ */ jsx48(
|
|
12327
|
-
BasicInput15,
|
|
12328
|
-
{
|
|
12329
|
-
type: "number",
|
|
12330
|
-
min: 1,
|
|
12331
|
-
value: perDay,
|
|
12332
|
-
onChange: (e) => setPerDay(Math.max(1, Number(e.target.value) || 1))
|
|
12333
|
-
}
|
|
12334
|
-
)
|
|
12410
|
+
/* @__PURE__ */ jsx48(Label8, { className: "text-xs font-medium", children: "What it is called" }),
|
|
12411
|
+
/* @__PURE__ */ jsx48(BasicInput15, { value: title, onChange: (e) => setTitle(e.target.value) })
|
|
12335
12412
|
] }),
|
|
12336
|
-
/* @__PURE__ */ jsxs44("
|
|
12337
|
-
/* @__PURE__ */
|
|
12338
|
-
|
|
12339
|
-
"select",
|
|
12340
|
-
{
|
|
12341
|
-
className: "h-9 rounded border bg-background px-2 text-sm",
|
|
12342
|
-
value: days,
|
|
12343
|
-
onChange: (e) => setDays(Number(e.target.value)),
|
|
12344
|
-
children: [7, 14, 30, 60, 90].map((n) => /* @__PURE__ */ jsxs44("option", { value: n, children: [
|
|
12345
|
-
n,
|
|
12346
|
-
" days"
|
|
12347
|
-
] }, n))
|
|
12348
|
-
}
|
|
12349
|
-
)
|
|
12350
|
-
] })
|
|
12351
|
-
] }),
|
|
12352
|
-
/* @__PURE__ */ jsxs44("div", { className: "flex flex-col gap-1.5", children: [
|
|
12353
|
-
/* @__PURE__ */ jsx48(Label8, { className: "text-xs font-medium", children: "Hours you are free" }),
|
|
12354
|
-
windows.map((w, i) => /* @__PURE__ */ jsxs44("div", { className: "flex items-center gap-2", children: [
|
|
12355
|
-
/* @__PURE__ */ jsxs44("label", { className: "flex w-20 items-center gap-1.5 text-xs", children: [
|
|
12413
|
+
/* @__PURE__ */ jsxs44("div", { className: "grid grid-cols-1 gap-2 @md:grid-cols-2", children: [
|
|
12414
|
+
/* @__PURE__ */ jsxs44("label", { className: "flex flex-col gap-1", children: [
|
|
12415
|
+
/* @__PURE__ */ jsx48(Label8, { className: "text-xs font-medium", children: "How long one appointment is" }),
|
|
12356
12416
|
/* @__PURE__ */ jsx48(
|
|
12357
|
-
|
|
12417
|
+
"select",
|
|
12358
12418
|
{
|
|
12359
|
-
|
|
12360
|
-
|
|
12419
|
+
className: "h-9 rounded border bg-background px-2 text-sm",
|
|
12420
|
+
value: minutes,
|
|
12421
|
+
onChange: (e) => setMinutes(Number(e.target.value)),
|
|
12422
|
+
children: LENGTHS.map((n) => /* @__PURE__ */ jsxs44("option", { value: n, children: [
|
|
12423
|
+
n,
|
|
12424
|
+
" minutes"
|
|
12425
|
+
] }, n))
|
|
12361
12426
|
}
|
|
12362
|
-
)
|
|
12363
|
-
DAYS[i]?.label
|
|
12427
|
+
)
|
|
12364
12428
|
] }),
|
|
12365
|
-
|
|
12429
|
+
/* @__PURE__ */ jsxs44("label", { className: "flex flex-col gap-1", children: [
|
|
12430
|
+
/* @__PURE__ */ jsx48(Label8, { className: "text-xs font-medium", children: "Gap kept after each one" }),
|
|
12366
12431
|
/* @__PURE__ */ jsx48(
|
|
12367
|
-
|
|
12432
|
+
"select",
|
|
12368
12433
|
{
|
|
12369
|
-
|
|
12370
|
-
|
|
12371
|
-
|
|
12372
|
-
|
|
12434
|
+
className: "h-9 rounded border bg-background px-2 text-sm",
|
|
12435
|
+
value: buffer,
|
|
12436
|
+
onChange: (e) => setBuffer(Number(e.target.value)),
|
|
12437
|
+
children: [0, 5, 10, 15, 30].map((n) => /* @__PURE__ */ jsx48("option", { value: n, children: n === 0 ? "No gap \u2014 back to back" : `${n} minutes` }, n))
|
|
12373
12438
|
}
|
|
12374
|
-
)
|
|
12375
|
-
|
|
12439
|
+
)
|
|
12440
|
+
] }),
|
|
12441
|
+
/* @__PURE__ */ jsxs44("label", { className: "flex flex-col gap-1", children: [
|
|
12442
|
+
/* @__PURE__ */ jsx48(Label8, { className: "text-xs font-medium", children: "Earliest somebody may book" }),
|
|
12443
|
+
/* @__PURE__ */ jsx48(
|
|
12444
|
+
"select",
|
|
12445
|
+
{
|
|
12446
|
+
className: "h-9 rounded border bg-background px-2 text-sm",
|
|
12447
|
+
value: lead,
|
|
12448
|
+
onChange: (e) => setLead(Number(e.target.value)),
|
|
12449
|
+
children: [0, 60, 120, 240, 1440].map((n) => /* @__PURE__ */ jsx48("option", { value: n, children: n === 0 ? "Right away" : n === 1440 ? "A day from now" : `${n / 60} hour${n === 60 ? "" : "s"} from now` }, n))
|
|
12450
|
+
}
|
|
12451
|
+
)
|
|
12452
|
+
] }),
|
|
12453
|
+
/* @__PURE__ */ jsxs44("label", { className: "flex flex-col gap-1", children: [
|
|
12454
|
+
/* @__PURE__ */ jsx48(Label8, { className: "text-xs font-medium", children: "Most in one day" }),
|
|
12376
12455
|
/* @__PURE__ */ jsx48(
|
|
12377
12456
|
BasicInput15,
|
|
12378
12457
|
{
|
|
12379
|
-
type: "
|
|
12380
|
-
|
|
12381
|
-
value:
|
|
12382
|
-
onChange: (e) =>
|
|
12458
|
+
type: "number",
|
|
12459
|
+
min: 1,
|
|
12460
|
+
value: perDay,
|
|
12461
|
+
onChange: (e) => setPerDay(Math.max(1, Number(e.target.value) || 1))
|
|
12383
12462
|
}
|
|
12384
12463
|
)
|
|
12385
|
-
] })
|
|
12386
|
-
|
|
12387
|
-
|
|
12388
|
-
|
|
12389
|
-
|
|
12390
|
-
|
|
12464
|
+
] }),
|
|
12465
|
+
/* @__PURE__ */ jsxs44("label", { className: "flex flex-col gap-1", children: [
|
|
12466
|
+
/* @__PURE__ */ jsx48(Label8, { className: "text-xs font-medium", children: "How far ahead the page offers" }),
|
|
12467
|
+
/* @__PURE__ */ jsx48(
|
|
12468
|
+
"select",
|
|
12469
|
+
{
|
|
12470
|
+
className: "h-9 rounded border bg-background px-2 text-sm",
|
|
12471
|
+
value: days,
|
|
12472
|
+
onChange: (e) => setDays(Number(e.target.value)),
|
|
12473
|
+
children: [7, 14, 30, 60, 90].map((n) => /* @__PURE__ */ jsxs44("option", { value: n, children: [
|
|
12474
|
+
n,
|
|
12475
|
+
" days"
|
|
12476
|
+
] }, n))
|
|
12477
|
+
}
|
|
12478
|
+
)
|
|
12479
|
+
] })
|
|
12480
|
+
] }),
|
|
12481
|
+
/* @__PURE__ */ jsxs44("div", { className: "flex flex-col gap-1.5", children: [
|
|
12482
|
+
/* @__PURE__ */ jsx48(Label8, { className: "text-xs font-medium", children: "Hours you are free" }),
|
|
12483
|
+
windows.map((w, i) => /* @__PURE__ */ jsxs44("div", { className: "flex items-center gap-2", children: [
|
|
12484
|
+
/* @__PURE__ */ jsxs44("label", { className: "flex w-20 items-center gap-1.5 text-xs", children: [
|
|
12485
|
+
/* @__PURE__ */ jsx48(
|
|
12486
|
+
Checkbox7,
|
|
12487
|
+
{
|
|
12488
|
+
checked: w.on,
|
|
12489
|
+
onCheckedChange: (on) => setWindows((prev) => prev.map((x, j) => i === j ? { ...x, on: Boolean(on) } : x))
|
|
12490
|
+
}
|
|
12491
|
+
),
|
|
12492
|
+
DAYS[i]?.label
|
|
12493
|
+
] }),
|
|
12494
|
+
w.on ? /* @__PURE__ */ jsxs44(Fragment22, { children: [
|
|
12495
|
+
/* @__PURE__ */ jsx48(
|
|
12496
|
+
BasicInput15,
|
|
12497
|
+
{
|
|
12498
|
+
type: "time",
|
|
12499
|
+
className: "h-8 w-28",
|
|
12500
|
+
value: w.from,
|
|
12501
|
+
onChange: (e) => setWindows((prev) => prev.map((x, j) => i === j ? { ...x, from: e.target.value } : x))
|
|
12502
|
+
}
|
|
12503
|
+
),
|
|
12504
|
+
/* @__PURE__ */ jsx48("span", { className: "text-xs text-muted-foreground", children: "to" }),
|
|
12505
|
+
/* @__PURE__ */ jsx48(
|
|
12506
|
+
BasicInput15,
|
|
12507
|
+
{
|
|
12508
|
+
type: "time",
|
|
12509
|
+
className: "h-8 w-28",
|
|
12510
|
+
value: w.to,
|
|
12511
|
+
onChange: (e) => setWindows((prev) => prev.map((x, j) => i === j ? { ...x, to: e.target.value } : x))
|
|
12512
|
+
}
|
|
12513
|
+
)
|
|
12514
|
+
] }) : /* @__PURE__ */ jsx48("span", { className: "text-xs text-muted-foreground", children: "not taking bookings" })
|
|
12515
|
+
] }, w.weekday))
|
|
12516
|
+
] }),
|
|
12517
|
+
/* @__PURE__ */ jsxs44("div", { className: "flex flex-col gap-1.5", children: [
|
|
12518
|
+
/* @__PURE__ */ jsx48(Label8, { className: "text-xs font-medium", children: "What to ask the person booking" }),
|
|
12519
|
+
askable.length === 0 ? /* @__PURE__ */ jsx48("p", { className: "text-xs text-muted-foreground", children: "This table has no fields yet, so there is nothing a booking page could ask for. Add a field first \u2014 every question is one of this table's own fields." }) : /* @__PURE__ */ jsx48("div", { className: "flex flex-wrap gap-x-4 gap-y-1.5", children: askable.map((f) => /* @__PURE__ */ jsxs44("label", { className: "flex items-center gap-1.5 text-xs", children: [
|
|
12520
|
+
/* @__PURE__ */ jsx48(
|
|
12521
|
+
Checkbox7,
|
|
12522
|
+
{
|
|
12523
|
+
checked: asked.includes(f.key),
|
|
12524
|
+
onCheckedChange: (on) => setAsked((prev) => on ? [...prev, f.key] : prev.filter((k) => k !== f.key))
|
|
12525
|
+
}
|
|
12526
|
+
),
|
|
12527
|
+
fieldName(f)
|
|
12528
|
+
] }, f.key)) }),
|
|
12529
|
+
/* @__PURE__ */ jsx48("p", { className: "text-xs text-muted-foreground", children: "The time, whether it is booked or cancelled, and who it is with are filled in by the store \u2014 a booking page cannot ask a visitor for any of the three." })
|
|
12530
|
+
] }),
|
|
12531
|
+
/* @__PURE__ */ jsxs44("label", { className: "flex flex-col gap-1", children: [
|
|
12532
|
+
/* @__PURE__ */ jsx48(Label8, { className: "text-xs font-medium", children: "What they see after booking" }),
|
|
12391
12533
|
/* @__PURE__ */ jsx48(
|
|
12392
|
-
|
|
12534
|
+
BasicTextarea7,
|
|
12393
12535
|
{
|
|
12394
|
-
|
|
12395
|
-
|
|
12536
|
+
rows: 2,
|
|
12537
|
+
value: confirmation,
|
|
12538
|
+
placeholder: "You're booked. We'll send a reminder the day before \u2014 reply to that message to move it.",
|
|
12539
|
+
onChange: (e) => setConfirmation(e.target.value)
|
|
12540
|
+
}
|
|
12541
|
+
)
|
|
12542
|
+
] }),
|
|
12543
|
+
shown ? /* @__PURE__ */ jsxs44("p", { className: "rounded-md border bg-muted/40 p-2.5 text-xs", children: [
|
|
12544
|
+
"Saved. The page offers ",
|
|
12545
|
+
shown.slot_minutes,
|
|
12546
|
+
"-minute appointments in ",
|
|
12547
|
+
shown.timezone,
|
|
12548
|
+
", up to",
|
|
12549
|
+
" ",
|
|
12550
|
+
shown.max_per_day,
|
|
12551
|
+
" a day, ",
|
|
12552
|
+
shown.days,
|
|
12553
|
+
" days ahead",
|
|
12554
|
+
shown.buffer_minutes > 0 ? `, with ${shown.buffer_minutes} minutes between them` : "",
|
|
12555
|
+
":",
|
|
12556
|
+
" ",
|
|
12557
|
+
shown.windows.map(
|
|
12558
|
+
(w) => `${DAYS.find((d) => d.weekday === w.weekday)?.label ?? w.weekday} ${w.from}\u2013${w.to}`
|
|
12559
|
+
).join(", "),
|
|
12560
|
+
"."
|
|
12561
|
+
] }) : null,
|
|
12562
|
+
url ? /* @__PURE__ */ jsxs44("div", { className: "flex flex-wrap items-center gap-2 rounded-md border p-2.5", children: [
|
|
12563
|
+
/* @__PURE__ */ jsx48("span", { className: "min-w-0 flex-1 break-all text-xs", children: url }),
|
|
12564
|
+
/* @__PURE__ */ jsx48(
|
|
12565
|
+
Button39,
|
|
12566
|
+
{
|
|
12567
|
+
size: "sm",
|
|
12568
|
+
variant: "outline",
|
|
12569
|
+
onClick: () => {
|
|
12570
|
+
void navigator.clipboard.writeText(url).then(() => {
|
|
12571
|
+
setCopied(true);
|
|
12572
|
+
window.setTimeout(() => setCopied(false), 1600);
|
|
12573
|
+
}).catch(() => setCopied(false));
|
|
12574
|
+
},
|
|
12575
|
+
children: copied ? "Copied" : "Copy link"
|
|
12396
12576
|
}
|
|
12397
12577
|
),
|
|
12398
|
-
|
|
12399
|
-
|
|
12400
|
-
|
|
12401
|
-
|
|
12402
|
-
|
|
12403
|
-
|
|
12404
|
-
|
|
12405
|
-
|
|
12406
|
-
|
|
12407
|
-
|
|
12408
|
-
|
|
12409
|
-
|
|
12410
|
-
|
|
12411
|
-
}
|
|
12412
|
-
)
|
|
12413
|
-
] }),
|
|
12414
|
-
shown ? /* @__PURE__ */ jsxs44("p", { className: "rounded-md border bg-muted/40 p-2.5 text-xs", children: [
|
|
12415
|
-
"Saved. The page offers ",
|
|
12416
|
-
shown.slot_minutes,
|
|
12417
|
-
"-minute appointments in ",
|
|
12418
|
-
shown.timezone,
|
|
12419
|
-
", up to",
|
|
12420
|
-
" ",
|
|
12421
|
-
shown.max_per_day,
|
|
12422
|
-
" a day, ",
|
|
12423
|
-
shown.days,
|
|
12424
|
-
" days ahead",
|
|
12425
|
-
shown.buffer_minutes > 0 ? `, with ${shown.buffer_minutes} minutes between them` : "",
|
|
12426
|
-
":",
|
|
12427
|
-
" ",
|
|
12428
|
-
shown.windows.map(
|
|
12429
|
-
(w) => `${DAYS.find((d) => d.weekday === w.weekday)?.label ?? w.weekday} ${w.from}\u2013${w.to}`
|
|
12430
|
-
).join(", "),
|
|
12431
|
-
"."
|
|
12432
|
-
] }) : null,
|
|
12433
|
-
url ? /* @__PURE__ */ jsxs44("div", { className: "flex flex-wrap items-center gap-2 rounded-md border p-2.5", children: [
|
|
12434
|
-
/* @__PURE__ */ jsx48("span", { className: "min-w-0 flex-1 break-all text-xs", children: url }),
|
|
12435
|
-
/* @__PURE__ */ jsx48(
|
|
12436
|
-
Button39,
|
|
12437
|
-
{
|
|
12438
|
-
size: "sm",
|
|
12439
|
-
variant: "outline",
|
|
12440
|
-
onClick: () => {
|
|
12441
|
-
void navigator.clipboard.writeText(url).then(() => {
|
|
12442
|
-
setCopied(true);
|
|
12443
|
-
window.setTimeout(() => setCopied(false), 1600);
|
|
12444
|
-
}).catch(() => setCopied(false));
|
|
12445
|
-
},
|
|
12446
|
-
children: copied ? "Copied" : "Copy link"
|
|
12447
|
-
}
|
|
12448
|
-
),
|
|
12449
|
-
/* @__PURE__ */ jsx48(
|
|
12450
|
-
Button39,
|
|
12451
|
-
{
|
|
12452
|
-
size: "sm",
|
|
12453
|
-
disabled: publishing,
|
|
12454
|
-
onClick: () => void publish(!(existing?.published_at && !existing.closed_at)),
|
|
12455
|
-
children: publishing ? "\u2026" : existing?.published_at && !existing.closed_at ? "Unpublish" : "Publish"
|
|
12456
|
-
}
|
|
12457
|
-
),
|
|
12458
|
-
/* @__PURE__ */ jsx48("p", { className: "w-full text-xs text-muted-foreground", children: existing?.published_at && !existing.closed_at ? "Open. Anyone with this link can book a time." : "Not open yet \u2014 the link does not take bookings until you publish it." })
|
|
12459
|
-
] }) : null
|
|
12460
|
-
] });
|
|
12578
|
+
/* @__PURE__ */ jsx48(
|
|
12579
|
+
Button39,
|
|
12580
|
+
{
|
|
12581
|
+
size: "sm",
|
|
12582
|
+
disabled: publishing,
|
|
12583
|
+
onClick: () => void publish(!(existing?.published_at && !existing.closed_at)),
|
|
12584
|
+
children: publishing ? "\u2026" : existing?.published_at && !existing.closed_at ? "Unpublish" : "Publish"
|
|
12585
|
+
}
|
|
12586
|
+
),
|
|
12587
|
+
/* @__PURE__ */ jsx48("p", { className: "w-full text-xs text-muted-foreground", children: existing?.published_at && !existing.closed_at ? "Open. Anyone with this link can book a time." : "Not open yet \u2014 the link does not take bookings until you publish it." })
|
|
12588
|
+
] }) : null
|
|
12589
|
+
] })
|
|
12590
|
+
);
|
|
12461
12591
|
}
|
|
12462
12592
|
|
|
12463
12593
|
// src/BookingSlots.tsx
|
|
@@ -14268,6 +14398,7 @@ export {
|
|
|
14268
14398
|
MyChecklistSteps,
|
|
14269
14399
|
NEEDS_A_SENTENCE,
|
|
14270
14400
|
NOT_ANSWERED_YET,
|
|
14401
|
+
NOT_DRAWN_HERE,
|
|
14271
14402
|
NO_AGENT_PORT,
|
|
14272
14403
|
NO_CHAT_REASON,
|
|
14273
14404
|
NO_COLUMNS_WHY,
|
|
@@ -14336,6 +14467,8 @@ export {
|
|
|
14336
14467
|
chooseSurface,
|
|
14337
14468
|
colorFromTheValue,
|
|
14338
14469
|
columnForField,
|
|
14470
|
+
conditionInWords,
|
|
14471
|
+
conditionIsSimple,
|
|
14339
14472
|
conditionValue,
|
|
14340
14473
|
controlFor,
|
|
14341
14474
|
currencyCodeFor,
|