@bikdotai/bik-component-library 0.0.867 → 0.0.868-beta.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.
Files changed (91) hide show
  1. package/dist/cjs/components/chip-selector/ChipSelector.js +2 -0
  2. package/dist/cjs/components/chip-selector/ChipSelector.js.map +1 -0
  3. package/dist/cjs/components/chip-selector/ChipSelector.styled.js +36 -0
  4. package/dist/cjs/components/chip-selector/ChipSelector.styled.js.map +1 -0
  5. package/dist/cjs/components/chip-selector/ChipSelectorGroup.js +2 -0
  6. package/dist/cjs/components/chip-selector/ChipSelectorGroup.js.map +1 -0
  7. package/dist/cjs/components/combo-box/ComboBox.js +2 -0
  8. package/dist/cjs/components/combo-box/ComboBox.js.map +1 -0
  9. package/dist/cjs/components/combo-box/ComboBox.styled.js +33 -0
  10. package/dist/cjs/components/combo-box/ComboBox.styled.js.map +1 -0
  11. package/dist/cjs/components/datePicker/DatePickerWrapper.js +1 -1
  12. package/dist/cjs/components/datePicker/DatePickerWrapper.js.map +1 -1
  13. package/dist/cjs/components/schedule-builder/RefreshSegmentToggle.js +2 -0
  14. package/dist/cjs/components/schedule-builder/RefreshSegmentToggle.js.map +1 -0
  15. package/dist/cjs/components/schedule-builder/ScheduleBuilder.js +2 -0
  16. package/dist/cjs/components/schedule-builder/ScheduleBuilder.js.map +1 -0
  17. package/dist/cjs/components/schedule-builder/ScheduleBuilder.styled.js +138 -0
  18. package/dist/cjs/components/schedule-builder/ScheduleBuilder.styled.js.map +1 -0
  19. package/dist/cjs/components/schedule-builder/ScheduleEndPicker.js +2 -0
  20. package/dist/cjs/components/schedule-builder/ScheduleEndPicker.js.map +1 -0
  21. package/dist/cjs/components/schedule-builder/ScheduleFrequencyPicker.js +2 -0
  22. package/dist/cjs/components/schedule-builder/ScheduleFrequencyPicker.js.map +1 -0
  23. package/dist/cjs/components/schedule-builder/ScheduleHelper.js +2 -0
  24. package/dist/cjs/components/schedule-builder/ScheduleHelper.js.map +1 -0
  25. package/dist/cjs/components/schedule-builder/SendModeSelector.js +2 -0
  26. package/dist/cjs/components/schedule-builder/SendModeSelector.js.map +1 -0
  27. package/dist/cjs/components/schedule-builder/StartDateTimePicker.js +2 -0
  28. package/dist/cjs/components/schedule-builder/StartDateTimePicker.js.map +1 -0
  29. package/dist/cjs/components/schedule-builder/UpcomingRunsPreview.js +2 -0
  30. package/dist/cjs/components/schedule-builder/UpcomingRunsPreview.js.map +1 -0
  31. package/dist/cjs/components/schedule-builder/model.js +2 -0
  32. package/dist/cjs/components/schedule-builder/model.js.map +1 -0
  33. package/dist/cjs/index.js +1 -1
  34. package/dist/esm/components/chip-selector/ChipSelector.d.ts +9 -0
  35. package/dist/esm/components/chip-selector/ChipSelector.js +27 -0
  36. package/dist/esm/components/chip-selector/ChipSelector.js.map +1 -0
  37. package/dist/esm/components/chip-selector/ChipSelector.styled.d.ts +10 -0
  38. package/dist/esm/components/chip-selector/ChipSelector.styled.js +48 -0
  39. package/dist/esm/components/chip-selector/ChipSelector.styled.js.map +1 -0
  40. package/dist/esm/components/chip-selector/ChipSelectorGroup.d.ts +10 -0
  41. package/dist/esm/components/chip-selector/ChipSelectorGroup.js +48 -0
  42. package/dist/esm/components/chip-selector/ChipSelectorGroup.js.map +1 -0
  43. package/dist/esm/components/chip-selector/index.d.ts +4 -0
  44. package/dist/esm/components/chip-selector/model.d.ts +106 -0
  45. package/dist/esm/components/combo-box/ComboBox.d.ts +15 -0
  46. package/dist/esm/components/combo-box/ComboBox.js +118 -0
  47. package/dist/esm/components/combo-box/ComboBox.js.map +1 -0
  48. package/dist/esm/components/combo-box/ComboBox.styled.d.ts +12 -0
  49. package/dist/esm/components/combo-box/ComboBox.styled.js +40 -0
  50. package/dist/esm/components/combo-box/ComboBox.styled.js.map +1 -0
  51. package/dist/esm/components/combo-box/index.d.ts +3 -0
  52. package/dist/esm/components/combo-box/model.d.ts +55 -0
  53. package/dist/esm/components/datePicker/DatePickerWrapper.d.ts +7 -0
  54. package/dist/esm/components/datePicker/DatePickerWrapper.js +66 -64
  55. package/dist/esm/components/datePicker/DatePickerWrapper.js.map +1 -1
  56. package/dist/esm/components/datePicker/index.d.ts +1 -0
  57. package/dist/esm/components/schedule-builder/RefreshSegmentToggle.d.ts +22 -0
  58. package/dist/esm/components/schedule-builder/RefreshSegmentToggle.js +31 -0
  59. package/dist/esm/components/schedule-builder/RefreshSegmentToggle.js.map +1 -0
  60. package/dist/esm/components/schedule-builder/ScheduleBuilder.d.ts +88 -0
  61. package/dist/esm/components/schedule-builder/ScheduleBuilder.js +105 -0
  62. package/dist/esm/components/schedule-builder/ScheduleBuilder.js.map +1 -0
  63. package/dist/esm/components/schedule-builder/ScheduleBuilder.styled.d.ts +81 -0
  64. package/dist/esm/components/schedule-builder/ScheduleBuilder.styled.js +168 -0
  65. package/dist/esm/components/schedule-builder/ScheduleBuilder.styled.js.map +1 -0
  66. package/dist/esm/components/schedule-builder/ScheduleEndPicker.d.ts +17 -0
  67. package/dist/esm/components/schedule-builder/ScheduleEndPicker.js +105 -0
  68. package/dist/esm/components/schedule-builder/ScheduleEndPicker.js.map +1 -0
  69. package/dist/esm/components/schedule-builder/ScheduleFrequencyPicker.d.ts +21 -0
  70. package/dist/esm/components/schedule-builder/ScheduleFrequencyPicker.js +136 -0
  71. package/dist/esm/components/schedule-builder/ScheduleFrequencyPicker.js.map +1 -0
  72. package/dist/esm/components/schedule-builder/ScheduleHelper.d.ts +110 -0
  73. package/dist/esm/components/schedule-builder/ScheduleHelper.js +196 -0
  74. package/dist/esm/components/schedule-builder/ScheduleHelper.js.map +1 -0
  75. package/dist/esm/components/schedule-builder/SendModeSelector.d.ts +29 -0
  76. package/dist/esm/components/schedule-builder/SendModeSelector.js +41 -0
  77. package/dist/esm/components/schedule-builder/SendModeSelector.js.map +1 -0
  78. package/dist/esm/components/schedule-builder/StartDateTimePicker.d.ts +44 -0
  79. package/dist/esm/components/schedule-builder/StartDateTimePicker.js +119 -0
  80. package/dist/esm/components/schedule-builder/StartDateTimePicker.js.map +1 -0
  81. package/dist/esm/components/schedule-builder/UpcomingRunsPreview.d.ts +19 -0
  82. package/dist/esm/components/schedule-builder/UpcomingRunsPreview.js +44 -0
  83. package/dist/esm/components/schedule-builder/UpcomingRunsPreview.js.map +1 -0
  84. package/dist/esm/components/schedule-builder/index.d.ts +17 -0
  85. package/dist/esm/components/schedule-builder/model.d.ts +69 -0
  86. package/dist/esm/components/schedule-builder/model.js +8 -0
  87. package/dist/esm/components/schedule-builder/model.js.map +1 -0
  88. package/dist/esm/index.d.ts +3 -0
  89. package/dist/esm/index.js +716 -675
  90. package/dist/esm/index.js.map +1 -1
  91. package/package.json +1 -1
@@ -0,0 +1,22 @@
1
+ import { default as React } from 'react';
2
+ export interface RefreshSegmentToggleProps {
3
+ value: boolean;
4
+ onChange: (value: boolean) => void;
5
+ /**
6
+ * False when the audience cannot be recomputed — a static uploaded list, for
7
+ * instance. The switch reads off and goes inert rather than disappearing, so
8
+ * the merchant can see the option exists and is unavailable.
9
+ */
10
+ canRefresh?: boolean;
11
+ title?: string;
12
+ caption?: string;
13
+ 'data-test'?: string;
14
+ }
15
+ /**
16
+ * "Refresh segment before each run".
17
+ *
18
+ * Kept separate from the pickers because it is not part of the schedule — it
19
+ * decides how the audience is resolved at send time, and a screen may want the
20
+ * schedule without offering this at all.
21
+ */
22
+ export declare const RefreshSegmentToggle: React.FC<RefreshSegmentToggleProps>;
@@ -0,0 +1,31 @@
1
+ import { jsxs as o, jsx as e } from "react/jsx-runtime";
2
+ import { COLORS as t } from "../../constants/Theme.js";
3
+ import { TitleSmall as h, BodyCaption as l } from "../TypographyStyle.js";
4
+ import { RefreshSegmentRow as f, RefreshSegmentCopy as d } from "./ScheduleBuilder.styled.js";
5
+ import { Switch as p } from "../switch/Switch.js";
6
+ const b = ({
7
+ value: n,
8
+ onChange: m,
9
+ canRefresh: r = !0,
10
+ title: s = "Refresh segment before each run",
11
+ caption: i = "Recomputes who is in the segment before each run",
12
+ "data-test": a = "refresh-segment-before-each-run"
13
+ }) => /* @__PURE__ */ o(f, { children: [
14
+ /* @__PURE__ */ o(d, { children: [
15
+ /* @__PURE__ */ e(h, { color: t.content.primary, children: s }),
16
+ /* @__PURE__ */ e(l, { color: t.content.secondary, children: i })
17
+ ] }),
18
+ /* @__PURE__ */ e(
19
+ p,
20
+ {
21
+ value: r && n,
22
+ disabled: !r,
23
+ onValueChange: async (c) => m(c),
24
+ "data-test": a
25
+ }
26
+ )
27
+ ] });
28
+ export {
29
+ b as RefreshSegmentToggle
30
+ };
31
+ //# sourceMappingURL=RefreshSegmentToggle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RefreshSegmentToggle.js","sources":["../../../../src/components/schedule-builder/RefreshSegmentToggle.tsx"],"sourcesContent":["import React from 'react';\nimport { COLORS } from '../../constants/Theme';\nimport { Switch } from '../switch';\nimport { BodyCaption, TitleSmall } from '../TypographyStyle';\nimport {\n\tRefreshSegmentCopy,\n\tRefreshSegmentRow,\n} from './ScheduleBuilder.styled';\n\nexport interface RefreshSegmentToggleProps {\n\tvalue: boolean;\n\tonChange: (value: boolean) => void;\n\t/**\n\t * False when the audience cannot be recomputed — a static uploaded list, for\n\t * instance. The switch reads off and goes inert rather than disappearing, so\n\t * the merchant can see the option exists and is unavailable.\n\t */\n\tcanRefresh?: boolean;\n\ttitle?: string;\n\tcaption?: string;\n\t'data-test'?: string;\n}\n\n/**\n * \"Refresh segment before each run\".\n *\n * Kept separate from the pickers because it is not part of the schedule — it\n * decides how the audience is resolved at send time, and a screen may want the\n * schedule without offering this at all.\n */\nexport const RefreshSegmentToggle: React.FC<RefreshSegmentToggleProps> = ({\n\tvalue,\n\tonChange,\n\tcanRefresh = true,\n\ttitle = 'Refresh segment before each run',\n\tcaption = 'Recomputes who is in the segment before each run',\n\t'data-test': dataTest = 'refresh-segment-before-each-run',\n}) => (\n\t<RefreshSegmentRow>\n\t\t<RefreshSegmentCopy>\n\t\t\t<TitleSmall color={COLORS.content.primary}>{title}</TitleSmall>\n\t\t\t<BodyCaption color={COLORS.content.secondary}>{caption}</BodyCaption>\n\t\t</RefreshSegmentCopy>\n\t\t<Switch\n\t\t\tvalue={canRefresh && value}\n\t\t\tdisabled={!canRefresh}\n\t\t\t// Switch's contract is async; this toggle is synchronous, so adapt rather\n\t\t\t// than push the Promise into every caller.\n\t\t\tonValueChange={async (next: boolean) => onChange(next)}\n\t\t\tdata-test={dataTest}\n\t\t/>\n\t</RefreshSegmentRow>\n);\n"],"names":["RefreshSegmentToggle","value","onChange","canRefresh","title","caption","dataTest","RefreshSegmentRow","jsxs","RefreshSegmentCopy","jsx","TitleSmall","COLORS","BodyCaption","Switch","next"],"mappings":";;;;;AA8BO,MAAMA,IAA4D,CAAC;AAAA,EACzE,OAAAC;AAAA,EACA,UAAAC;AAAA,EACA,YAAAC,IAAa;AAAA,EACb,OAAAC,IAAQ;AAAA,EACR,SAAAC,IAAU;AAAA,EACV,aAAaC,IAAW;AACzB,wBACEC,GAAA,EACA,UAAA;AAAA,EAAA,gBAAAC,EAACC,GAAA,EACA,UAAA;AAAA,IAAA,gBAAAC,EAACC,GAAA,EAAW,OAAOC,EAAO,QAAQ,SAAU,UAAAR,GAAM;AAAA,sBACjDS,GAAA,EAAY,OAAOD,EAAO,QAAQ,WAAY,UAAAP,EAAA,CAAQ;AAAA,EAAA,GACxD;AAAA,EACA,gBAAAK;AAAA,IAACI;AAAA,IAAA;AAAA,MACA,OAAOX,KAAcF;AAAA,MACrB,UAAU,CAACE;AAAA,MAGX,eAAe,OAAOY,MAAkBb,EAASa,CAAI;AAAA,MACrD,aAAWT;AAAA,IAAA;AAAA,EAAA;AACZ,EAAA,CACD;"}
@@ -0,0 +1,88 @@
1
+ import { default as React } from 'react';
2
+ import { RecurrenceValue, SEND_MODE } from './model';
3
+ import { SendModeItem } from './SendModeSelector';
4
+ export interface ScheduleBuilderProps {
5
+ /** Which mode is selected. Drives what is rendered below the cards. */
6
+ sendMode?: SEND_MODE;
7
+ onSendModeChange: (mode: SEND_MODE) => void;
8
+ /**
9
+ * Modes on offer. Pass a subset to drop one — a screen that cannot send
10
+ * immediately should not show a "Send now" card it will reject.
11
+ */
12
+ sendModeOptions?: SendModeItem<SEND_MODE>[];
13
+ /** The date the schedule starts from. For RECURRING it is the first run. */
14
+ date?: Date;
15
+ onDateChange: (date: Date) => void;
16
+ /**
17
+ * Date the runs preview counts from, when it should differ from `date`.
18
+ *
19
+ * `date` follows the picker and changes the instant a day is clicked, which is
20
+ * usually too eager for the preview: a host validating the time separately does
21
+ * not want runs listed at a time that has not passed validation. Pass the
22
+ * validated value here and leave it undefined to hide the preview until then.
23
+ * Defaults to `date`.
24
+ */
25
+ previewStartDate?: Date;
26
+ /** 12-hour clock, "1"–"12". Empty while nothing is chosen. */
27
+ hours: string;
28
+ /** "0"–"59". Empty while nothing is chosen. */
29
+ minutes: string;
30
+ isAm: boolean;
31
+ /** Fires only for a parseable time, so partial typing does not clear state. */
32
+ onTimeChange: (time: {
33
+ hours: string;
34
+ minutes: string;
35
+ }) => void;
36
+ onMeridiemChange: (isAm: boolean) => void;
37
+ onTimeInvalidBlur?: () => void;
38
+ /** Shown under the time field. The caller owns validation. */
39
+ timeErrorMessage?: string;
40
+ /** Earliest selectable date, normally now plus whatever lead time applies. */
41
+ minDate?: Date;
42
+ /** The recurrence. Only read when sendMode is RECURRING. */
43
+ recurrence?: RecurrenceValue;
44
+ /**
45
+ * Receives only the fields that changed, so a caller holding this in redux can
46
+ * dispatch one action per field instead of replacing the whole object.
47
+ */
48
+ onRecurrenceChange: (patch: Partial<RecurrenceValue>) => void;
49
+ /** How many runs the preview lists. */
50
+ previewCount?: number;
51
+ /** Hide the runs preview, for a compact form that shows the summary elsewhere. */
52
+ hideUpcomingRuns?: boolean;
53
+ /** Greys out every control — an in-flight campaign that can no longer be moved. */
54
+ disabled?: boolean;
55
+ /** Menu width for the frequency dropdown; defaults to its button's width. */
56
+ frequencyMenuWidth?: string;
57
+ /**
58
+ * Rendered between the send-mode cards and the date/time fields. For a host
59
+ * extra that belongs at the top — a best-time-to-send card, a warning banner.
60
+ */
61
+ children?: React.ReactNode;
62
+ /**
63
+ * Rendered at the very bottom, after the runs preview, and only while the
64
+ * schedule is recurring.
65
+ *
66
+ * Separate from `children` because position is the whole point: a
67
+ * per-run setting like "refresh the audience each time" reads as a footnote to
68
+ * the schedule it modifies, so it has to follow the runs rather than precede
69
+ * the date.
70
+ */
71
+ recurrenceFooter?: React.ReactNode;
72
+ 'data-test'?: string;
73
+ }
74
+ /**
75
+ * Picks when something sends — once, at a set time, or on a repeating schedule.
76
+ *
77
+ * Controlled and free of any app state: values in, change handlers out. It owns
78
+ * the send-mode cards, the date and time, and — for a repeating schedule — the
79
+ * frequency, what it repeats on, when it ends, and a preview of the next runs.
80
+ *
81
+ * Deliberately domain-neutral. Nothing about campaigns, audiences or sending
82
+ * lives here, so anything that needs a schedule can use it. Host-specific extras
83
+ * go through `children`, which renders below the mode cards.
84
+ *
85
+ * Every part is also exported on its own, for a screen that needs the end picker
86
+ * or the runs preview without the rest.
87
+ */
88
+ export declare const ScheduleBuilder: React.FC<ScheduleBuilderProps>;
@@ -0,0 +1,105 @@
1
+ import { jsxs as m, jsx as e, Fragment as x } from "react/jsx-runtime";
2
+ import { useMemo as s } from "react";
3
+ import { SEND_MODE as o } from "./model.js";
4
+ import { Column as u, SectionDivider as y } from "./ScheduleBuilder.styled.js";
5
+ import { ScheduleEndPicker as G } from "./ScheduleEndPicker.js";
6
+ import { ScheduleFrequencyPicker as L } from "./ScheduleFrequencyPicker.js";
7
+ import { ScheduleHelper as W, UPCOMING_RUNS_PREVIEW_COUNT as j } from "./ScheduleHelper.js";
8
+ import { SendModeSelector as H } from "./SendModeSelector.js";
9
+ import { StartDateTimePicker as M } from "./StartDateTimePicker.js";
10
+ import { UpcomingRunsPreview as q } from "./UpcomingRunsPreview.js";
11
+ const A = [
12
+ { value: o.SEND_NOW, label: "Send now" },
13
+ { value: o.SCHEDULE, label: "Schedule" },
14
+ { value: o.RECURRING, label: "Set as recurring" }
15
+ ], ee = ({
16
+ sendMode: r,
17
+ onSendModeChange: h,
18
+ sendModeOptions: E = A,
19
+ date: a,
20
+ onDateChange: f,
21
+ previewStartDate: c,
22
+ hours: N,
23
+ minutes: g,
24
+ isAm: D,
25
+ onTimeChange: R,
26
+ onMeridiemChange: U,
27
+ onTimeInvalidBlur: _,
28
+ timeErrorMessage: b,
29
+ minDate: v,
30
+ recurrence: t,
31
+ onRecurrenceChange: d,
32
+ previewCount: p = j,
33
+ hideUpcomingRuns: O = !1,
34
+ disabled: C = !1,
35
+ frequencyMenuWidth: P,
36
+ children: F,
37
+ recurrenceFooter: I,
38
+ "data-test": T = "schedule-builder"
39
+ }) => {
40
+ const l = r === o.RECURRING, k = !!r && r !== o.SEND_NOW, i = s(() => new W(t), [t]), S = c === void 0 ? a : c, n = s(
41
+ () => l ? i.computeUpcomingRuns(S, p) : [],
42
+ [i, S, p, l]
43
+ ), w = s(
44
+ () => i.buildSummary(n),
45
+ [i, n]
46
+ );
47
+ return /* @__PURE__ */ m(u, { gap: 16, "data-test": T, children: [
48
+ /* @__PURE__ */ e(
49
+ H,
50
+ {
51
+ options: E,
52
+ value: r,
53
+ onChange: h,
54
+ disabled: C,
55
+ "data-test": "schedule-builder-send-mode"
56
+ }
57
+ ),
58
+ F,
59
+ k && /* @__PURE__ */ m(x, { children: [
60
+ /* @__PURE__ */ e(y, {}),
61
+ /* @__PURE__ */ m(u, { gap: 12, children: [
62
+ /* @__PURE__ */ e(
63
+ M,
64
+ {
65
+ date: a,
66
+ onDateChange: f,
67
+ hours: N,
68
+ minutes: g,
69
+ isAm: D,
70
+ onTimeChange: R,
71
+ onMeridiemChange: U,
72
+ onTimeInvalidBlur: _,
73
+ timeErrorMessage: b,
74
+ dateLabel: l ? "Start date" : "Date",
75
+ minDate: v
76
+ }
77
+ ),
78
+ l && /* @__PURE__ */ m(u, { gap: 12, "data-test": "schedule-builder-recurrence", children: [
79
+ /* @__PURE__ */ e(
80
+ L,
81
+ {
82
+ value: t ?? {},
83
+ onChange: d,
84
+ frequencyMenuWidth: P
85
+ }
86
+ ),
87
+ /* @__PURE__ */ e(
88
+ G,
89
+ {
90
+ value: t ?? {},
91
+ onChange: d,
92
+ minEndDate: a
93
+ }
94
+ ),
95
+ !O && /* @__PURE__ */ e(q, { runs: n, summary: w }),
96
+ I
97
+ ] })
98
+ ] })
99
+ ] })
100
+ ] });
101
+ };
102
+ export {
103
+ ee as ScheduleBuilder
104
+ };
105
+ //# sourceMappingURL=ScheduleBuilder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ScheduleBuilder.js","sources":["../../../../src/components/schedule-builder/ScheduleBuilder.tsx"],"sourcesContent":["import React, { useMemo } from 'react';\nimport { RecurrenceValue, SEND_MODE } from './model';\nimport { Column, SectionDivider } from './ScheduleBuilder.styled';\nimport { ScheduleEndPicker } from './ScheduleEndPicker';\nimport { ScheduleFrequencyPicker } from './ScheduleFrequencyPicker';\nimport { ScheduleHelper, UPCOMING_RUNS_PREVIEW_COUNT } from './ScheduleHelper';\nimport { SendModeItem, SendModeSelector } from './SendModeSelector';\nimport { StartDateTimePicker } from './StartDateTimePicker';\nimport { UpcomingRunsPreview } from './UpcomingRunsPreview';\n\n/** The modes offered when the caller does not name its own. */\nconst DEFAULT_SEND_MODE_OPTIONS: SendModeItem<SEND_MODE>[] = [\n\t{ value: SEND_MODE.SEND_NOW, label: 'Send now' },\n\t{ value: SEND_MODE.SCHEDULE, label: 'Schedule' },\n\t{ value: SEND_MODE.RECURRING, label: 'Set as recurring' },\n];\n\nexport interface ScheduleBuilderProps {\n\t/** Which mode is selected. Drives what is rendered below the cards. */\n\tsendMode?: SEND_MODE;\n\tonSendModeChange: (mode: SEND_MODE) => void;\n\t/**\n\t * Modes on offer. Pass a subset to drop one — a screen that cannot send\n\t * immediately should not show a \"Send now\" card it will reject.\n\t */\n\tsendModeOptions?: SendModeItem<SEND_MODE>[];\n\n\t/** The date the schedule starts from. For RECURRING it is the first run. */\n\tdate?: Date;\n\tonDateChange: (date: Date) => void;\n\t/**\n\t * Date the runs preview counts from, when it should differ from `date`.\n\t *\n\t * `date` follows the picker and changes the instant a day is clicked, which is\n\t * usually too eager for the preview: a host validating the time separately does\n\t * not want runs listed at a time that has not passed validation. Pass the\n\t * validated value here and leave it undefined to hide the preview until then.\n\t * Defaults to `date`.\n\t */\n\tpreviewStartDate?: Date;\n\n\t/** 12-hour clock, \"1\"–\"12\". Empty while nothing is chosen. */\n\thours: string;\n\t/** \"0\"–\"59\". Empty while nothing is chosen. */\n\tminutes: string;\n\tisAm: boolean;\n\t/** Fires only for a parseable time, so partial typing does not clear state. */\n\tonTimeChange: (time: { hours: string; minutes: string }) => void;\n\tonMeridiemChange: (isAm: boolean) => void;\n\tonTimeInvalidBlur?: () => void;\n\t/** Shown under the time field. The caller owns validation. */\n\ttimeErrorMessage?: string;\n\t/** Earliest selectable date, normally now plus whatever lead time applies. */\n\tminDate?: Date;\n\n\t/** The recurrence. Only read when sendMode is RECURRING. */\n\trecurrence?: RecurrenceValue;\n\t/**\n\t * Receives only the fields that changed, so a caller holding this in redux can\n\t * dispatch one action per field instead of replacing the whole object.\n\t */\n\tonRecurrenceChange: (patch: Partial<RecurrenceValue>) => void;\n\n\t/** How many runs the preview lists. */\n\tpreviewCount?: number;\n\t/** Hide the runs preview, for a compact form that shows the summary elsewhere. */\n\thideUpcomingRuns?: boolean;\n\t/** Greys out every control — an in-flight campaign that can no longer be moved. */\n\tdisabled?: boolean;\n\t/** Menu width for the frequency dropdown; defaults to its button's width. */\n\tfrequencyMenuWidth?: string;\n\t/**\n\t * Rendered between the send-mode cards and the date/time fields. For a host\n\t * extra that belongs at the top — a best-time-to-send card, a warning banner.\n\t */\n\tchildren?: React.ReactNode;\n\t/**\n\t * Rendered at the very bottom, after the runs preview, and only while the\n\t * schedule is recurring.\n\t *\n\t * Separate from `children` because position is the whole point: a\n\t * per-run setting like \"refresh the audience each time\" reads as a footnote to\n\t * the schedule it modifies, so it has to follow the runs rather than precede\n\t * the date.\n\t */\n\trecurrenceFooter?: React.ReactNode;\n\t'data-test'?: string;\n}\n\n/**\n * Picks when something sends — once, at a set time, or on a repeating schedule.\n *\n * Controlled and free of any app state: values in, change handlers out. It owns\n * the send-mode cards, the date and time, and — for a repeating schedule — the\n * frequency, what it repeats on, when it ends, and a preview of the next runs.\n *\n * Deliberately domain-neutral. Nothing about campaigns, audiences or sending\n * lives here, so anything that needs a schedule can use it. Host-specific extras\n * go through `children`, which renders below the mode cards.\n *\n * Every part is also exported on its own, for a screen that needs the end picker\n * or the runs preview without the rest.\n */\nexport const ScheduleBuilder: React.FC<ScheduleBuilderProps> = ({\n\tsendMode,\n\tonSendModeChange,\n\tsendModeOptions = DEFAULT_SEND_MODE_OPTIONS,\n\tdate,\n\tonDateChange,\n\tpreviewStartDate,\n\thours,\n\tminutes,\n\tisAm,\n\tonTimeChange,\n\tonMeridiemChange,\n\tonTimeInvalidBlur,\n\ttimeErrorMessage,\n\tminDate,\n\trecurrence,\n\tonRecurrenceChange,\n\tpreviewCount = UPCOMING_RUNS_PREVIEW_COUNT,\n\thideUpcomingRuns = false,\n\tdisabled = false,\n\tfrequencyMenuWidth,\n\tchildren,\n\trecurrenceFooter,\n\t'data-test': dataTest = 'schedule-builder',\n}) => {\n\tconst isRecurring = sendMode === SEND_MODE.RECURRING;\n\t// Send-now has no date to pick; the other modes do.\n\tconst showFields = !!sendMode && sendMode !== SEND_MODE.SEND_NOW;\n\n\tconst helper = useMemo(() => new ScheduleHelper(recurrence), [recurrence]);\n\n\t/**\n\t * Runs are previewed from the chosen date — or from `previewStartDate` when the\n\t * host validates separately — so the list stays empty rather than counting from\n\t * today and then jumping once a real date lands.\n\t */\n\tconst previewFrom = previewStartDate === undefined ? date : previewStartDate;\n\n\tconst upcomingRuns = useMemo(\n\t\t() =>\n\t\t\tisRecurring ? helper.computeUpcomingRuns(previewFrom, previewCount) : [],\n\t\t[helper, previewFrom, previewCount, isRecurring],\n\t);\n\n\tconst summary = useMemo(\n\t\t() => helper.buildSummary(upcomingRuns),\n\t\t[helper, upcomingRuns],\n\t);\n\n\treturn (\n\t\t<Column gap={16} data-test={dataTest}>\n\t\t\t<SendModeSelector\n\t\t\t\toptions={sendModeOptions}\n\t\t\t\tvalue={sendMode}\n\t\t\t\tonChange={onSendModeChange}\n\t\t\t\tdisabled={disabled}\n\t\t\t\tdata-test=\"schedule-builder-send-mode\"\n\t\t\t/>\n\t\t\t{children}\n\t\t\t{showFields && (\n\t\t\t\t<>\n\t\t\t\t\t<SectionDivider />\n\t\t\t\t\t<Column gap={12}>\n\t\t\t\t\t\t<StartDateTimePicker\n\t\t\t\t\t\t\tdate={date}\n\t\t\t\t\t\t\tonDateChange={onDateChange}\n\t\t\t\t\t\t\thours={hours}\n\t\t\t\t\t\t\tminutes={minutes}\n\t\t\t\t\t\t\tisAm={isAm}\n\t\t\t\t\t\t\tonTimeChange={onTimeChange}\n\t\t\t\t\t\t\tonMeridiemChange={onMeridiemChange}\n\t\t\t\t\t\t\tonTimeInvalidBlur={onTimeInvalidBlur}\n\t\t\t\t\t\t\ttimeErrorMessage={timeErrorMessage}\n\t\t\t\t\t\t\t// \"Start date\" only reads right when runs follow it.\n\t\t\t\t\t\t\tdateLabel={isRecurring ? 'Start date' : 'Date'}\n\t\t\t\t\t\t\tminDate={minDate}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t{isRecurring && (\n\t\t\t\t\t\t\t<Column gap={12} data-test=\"schedule-builder-recurrence\">\n\t\t\t\t\t\t\t\t<ScheduleFrequencyPicker\n\t\t\t\t\t\t\t\t\tvalue={recurrence ?? {}}\n\t\t\t\t\t\t\t\t\tonChange={onRecurrenceChange}\n\t\t\t\t\t\t\t\t\tfrequencyMenuWidth={frequencyMenuWidth}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t<ScheduleEndPicker\n\t\t\t\t\t\t\t\t\tvalue={recurrence ?? {}}\n\t\t\t\t\t\t\t\t\tonChange={onRecurrenceChange}\n\t\t\t\t\t\t\t\t\tminEndDate={date}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t{!hideUpcomingRuns && (\n\t\t\t\t\t\t\t\t\t<UpcomingRunsPreview runs={upcomingRuns} summary={summary} />\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t{recurrenceFooter}\n\t\t\t\t\t\t\t</Column>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</Column>\n\t\t\t\t</>\n\t\t\t)}\n\t\t</Column>\n\t);\n};\n"],"names":["DEFAULT_SEND_MODE_OPTIONS","SEND_MODE","ScheduleBuilder","sendMode","onSendModeChange","sendModeOptions","date","onDateChange","previewStartDate","hours","minutes","isAm","onTimeChange","onMeridiemChange","onTimeInvalidBlur","timeErrorMessage","minDate","recurrence","onRecurrenceChange","previewCount","UPCOMING_RUNS_PREVIEW_COUNT","hideUpcomingRuns","disabled","frequencyMenuWidth","children","recurrenceFooter","dataTest","isRecurring","showFields","helper","useMemo","ScheduleHelper","previewFrom","upcomingRuns","summary","jsxs","Column","jsx","SendModeSelector","Fragment","SectionDivider","StartDateTimePicker","ScheduleFrequencyPicker","ScheduleEndPicker","UpcomingRunsPreview"],"mappings":"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"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * A labelled field column — "Start date" and "Time" sit side by side.
3
+ * 6px label-to-input gap comes from the design's `input-large` component.
4
+ */
5
+ export declare const FieldColumn: import('styled-components').StyledComponent<"div", any, {}, never>;
6
+ export declare const DateFieldColumn: import('styled-components').StyledComponent<"div", any, {}, never>;
7
+ /**
8
+ * Same share as the date column plus the am/pm dropdown's footprint (84px
9
+ * wide + 8px gap), so the time box itself matches the date box rather than
10
+ * being squeezed by the dropdown sitting beside it.
11
+ */
12
+ export declare const TimeFieldColumn: import('styled-components').StyledComponent<"div", any, {}, never>;
13
+ /**
14
+ * The Start date / Time row.
15
+ *
16
+ * Aligned to the top rather than centred: the time field grows taller when its
17
+ * validation message appears, and a centred row would shift the date field up
18
+ * and down with it.
19
+ */
20
+ export declare const FieldsRow: import('styled-components').StyledComponent<"div", any, {}, never>;
21
+ /** Wraps the date picker so its button matches the 48px input height. */
22
+ export declare const DatePickerSlot: import('styled-components').StyledComponent<"div", any, {}, never>;
23
+ /**
24
+ * The time box and its am/pm dropdown.
25
+ *
26
+ * Top-aligned rather than centred: the validation message renders inside the
27
+ * time slot, so a centred row would push am/pm downward as the message appears.
28
+ */
29
+ export declare const TimeInputRow: import('styled-components').StyledComponent<"div", any, {}, never>;
30
+ /** The hh:mm dropdown takes the free space; am/pm is fixed beside it. */
31
+ export declare const TimeDropdownSlot: import('styled-components').StyledComponent<"div", any, {}, never>;
32
+ export declare const MeridiemDropdownSlot: import('styled-components').StyledComponent<"div", any, {}, never>;
33
+ /**
34
+ * Frequency field. Fills its column, which is a DateFieldColumn so it takes the
35
+ * same share as Start date above it — the design has both as 337px halves of the
36
+ * 690px row, rather than a fixed 220px box that drifts as the panel resizes.
37
+ */
38
+ export declare const FrequencyDropdownSlot: import('styled-components').StyledComponent<"div", any, {}, never>;
39
+ /**
40
+ * Monthly date grid. Fixed at 337px so six CHIP_WIDTH chips and their 8px gaps
41
+ * wrap onto a tidy 6-per-row grid rather than reflowing with the panel width.
42
+ */
43
+ export declare const MonthDateGridSlot: import('styled-components').StyledComponent<"div", any, {}, never>;
44
+ /**
45
+ * Icon + text caption under a picker, for both validation errors and the
46
+ * skipped-month note. The icon is pinned to its 16px box and aligned to the
47
+ * first line — as a bare flex child it would stretch and open a wide gap.
48
+ */
49
+ export declare const CaptionWithIcon: import('styled-components').StyledComponent<"div", any, {}, never>;
50
+ /** Field label row — holds the caption and its required asterisk. */
51
+ export declare const FieldLabel: import('styled-components').StyledComponent<"div", any, {}, never>;
52
+ /** Frequency and time read in semibold inside the summary line. */
53
+ export declare const SummaryHighlight: import('styled-components').StyledComponent<"span", any, {}, never>;
54
+ export declare const RequiredMark: import('styled-components').StyledComponent<"span", any, {}, never>;
55
+ /** A single selectable send-mode card. */
56
+ export declare const SendModeOption: import('styled-components').StyledComponent<"div", any, {
57
+ active: boolean;
58
+ disabled: boolean;
59
+ }, never>;
60
+ /** The row of send-mode cards. */
61
+ export declare const SendModeRow: import('styled-components').StyledComponent<"div", any, {}, never>;
62
+ /** 1px rule between the send-mode radios and the fields below. */
63
+ export declare const SectionDivider: import('styled-components').StyledComponent<"div", any, {}, never>;
64
+ /** "Ends" row wraps when the three options do not fit on one line. */
65
+ export declare const EndsRow: import('styled-components').StyledComponent<"div", any, {}, never>;
66
+ /** 44px wide, 32px tall — the design's small input. */
67
+ export declare const RunCountInputWrapper: import('styled-components').StyledComponent<"div", any, {}, never>;
68
+ export declare const EndDateWrapper: import('styled-components').StyledComponent<"div", any, {}, never>;
69
+ export declare const UpcomingRunItem: import('styled-components').StyledComponent<"div", any, {
70
+ isLast: boolean;
71
+ }, never>;
72
+ export declare const UpcomingRunDot: import('styled-components').StyledComponent<"div", any, {}, never>;
73
+ export declare const RefreshSegmentRow: import('styled-components').StyledComponent<"div", any, {}, never>;
74
+ export declare const RefreshSegmentCopy: import('styled-components').StyledComponent<"div", any, {}, never>;
75
+ /** Generic vertical stack — the library cannot rely on the app's utility classes. */
76
+ export declare const Column: import('styled-components').StyledComponent<"div", any, {
77
+ gap?: number | undefined;
78
+ }, never>;
79
+ export declare const Row: import('styled-components').StyledComponent<"div", any, {
80
+ gap?: number | undefined;
81
+ }, never>;
@@ -0,0 +1,168 @@
1
+ import i from "styled-components";
2
+ import { COLORS as t } from "../../constants/Theme.js";
3
+ const o = 84, n = 8, d = i.div`
4
+ display: flex;
5
+ flex-direction: column;
6
+ min-width: 0;
7
+ gap: 6px;
8
+ `, l = i(d)`
9
+ flex: 1 1 0;
10
+ `, a = i(d)`
11
+ flex: 1 1 ${o + n}px;
12
+ `, s = i.div`
13
+ display: flex;
14
+ flex-direction: row;
15
+ gap: 16px;
16
+ width: 100%;
17
+ align-items: flex-start;
18
+ `, x = i.div`
19
+ height: 48px;
20
+ `, c = i.div`
21
+ display: flex;
22
+ flex-direction: row;
23
+ gap: ${n}px;
24
+ align-items: flex-start;
25
+ `, g = i.div`
26
+ flex: 1;
27
+ min-width: 0;
28
+ `, f = i.div`
29
+ flex: 0 0 ${o}px;
30
+ `, h = i.div`
31
+ width: 100%;
32
+ min-width: 0;
33
+ `, m = i.div`
34
+ display: flex;
35
+ flex-direction: column;
36
+ gap: 8px;
37
+ width: 337px;
38
+ max-width: 100%;
39
+ `, w = i.div`
40
+ display: flex;
41
+ flex-direction: row;
42
+ align-items: flex-start;
43
+ gap: 4px;
44
+
45
+ svg {
46
+ flex: 0 0 16px;
47
+ width: 16px;
48
+ height: 16px;
49
+ }
50
+ `, u = i.div`
51
+ display: flex;
52
+ align-items: center;
53
+ gap: 2px;
54
+ `, v = i.span`
55
+ font-weight: 600;
56
+ `, y = i.span`
57
+ color: ${t.content.negative};
58
+ `, b = i.div`
59
+ box-sizing: border-box;
60
+ display: flex;
61
+ flex-direction: row;
62
+ align-items: center;
63
+ gap: 4px;
64
+ padding: 16px;
65
+ flex: 1;
66
+ height: 56px;
67
+ border-radius: 4px;
68
+ border: 1px solid
69
+ ${(e) => e.active ? t.background.inverseLight : t.stroke.primary};
70
+ background: ${(e) => e.active ? t.background.brandLight : t.surface.standard};
71
+ cursor: ${(e) => e.disabled ? "not-allowed" : "pointer"};
72
+ opacity: ${(e) => e.disabled ? 0.6 : 1};
73
+ `, R = i.div`
74
+ display: flex;
75
+ flex-direction: row;
76
+ gap: 16px;
77
+ width: 100%;
78
+ `, k = i.div`
79
+ height: 1px;
80
+ width: 100%;
81
+ background: ${t.stroke.primary};
82
+ `, $ = i.div`
83
+ display: flex;
84
+ flex-direction: row;
85
+ align-items: center;
86
+ gap: 12px;
87
+ flex-wrap: wrap;
88
+ `, S = i.div`
89
+ width: 44px;
90
+ `, D = i.div`
91
+ width: 168px;
92
+ `, C = i.div`
93
+ position: relative;
94
+ display: flex;
95
+ flex-direction: row;
96
+ align-items: center;
97
+ gap: 8px;
98
+
99
+ /* connector spanning the 16px gap to the next run */
100
+ ::before {
101
+ content: '';
102
+ position: absolute;
103
+ left: 4.5px;
104
+ top: 100%;
105
+ height: 16px;
106
+ width: 1px;
107
+ background: ${(e) => e.isLast ? "transparent" : t.stroke.brandLightAlt};
108
+ }
109
+ `, I = i.div`
110
+ width: 10px;
111
+ height: 10px;
112
+ border-radius: 50%;
113
+ background: ${t.background.inverseLight};
114
+ flex-shrink: 0;
115
+ z-index: 1;
116
+ `, L = i.div`
117
+ display: flex;
118
+ flex-direction: row;
119
+ align-items: center;
120
+ gap: 12px;
121
+ width: 100%;
122
+ justify-content: space-between;
123
+ padding-top: 16px;
124
+ border-top: 1px solid ${t.stroke.primary};
125
+ `, M = i.div`
126
+ display: flex;
127
+ flex-direction: column;
128
+ gap: 4px;
129
+ `, F = i.div`
130
+ display: flex;
131
+ flex-direction: column;
132
+ gap: ${(e) => e.gap ?? 12}px;
133
+ width: 100%;
134
+ `, T = i.div`
135
+ display: flex;
136
+ flex-direction: row;
137
+ align-items: center;
138
+ gap: ${(e) => e.gap ?? 8}px;
139
+ `;
140
+ export {
141
+ w as CaptionWithIcon,
142
+ F as Column,
143
+ l as DateFieldColumn,
144
+ x as DatePickerSlot,
145
+ D as EndDateWrapper,
146
+ $ as EndsRow,
147
+ d as FieldColumn,
148
+ u as FieldLabel,
149
+ s as FieldsRow,
150
+ h as FrequencyDropdownSlot,
151
+ f as MeridiemDropdownSlot,
152
+ m as MonthDateGridSlot,
153
+ M as RefreshSegmentCopy,
154
+ L as RefreshSegmentRow,
155
+ y as RequiredMark,
156
+ T as Row,
157
+ S as RunCountInputWrapper,
158
+ k as SectionDivider,
159
+ b as SendModeOption,
160
+ R as SendModeRow,
161
+ v as SummaryHighlight,
162
+ g as TimeDropdownSlot,
163
+ a as TimeFieldColumn,
164
+ c as TimeInputRow,
165
+ I as UpcomingRunDot,
166
+ C as UpcomingRunItem
167
+ };
168
+ //# sourceMappingURL=ScheduleBuilder.styled.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ScheduleBuilder.styled.js","sources":["../../../../src/components/schedule-builder/ScheduleBuilder.styled.ts"],"sourcesContent":["import styled from 'styled-components';\nimport { COLORS } from '../../constants/Theme';\n\n/** Fixed width of the am/pm dropdown, and the gap separating it from the time box. */\nconst MERIDIEM_SLOT_WIDTH = 84;\nconst TIME_ROW_GAP = 8;\n\n/**\n * A labelled field column — \"Start date\" and \"Time\" sit side by side.\n * 6px label-to-input gap comes from the design's `input-large` component.\n */\nexport const FieldColumn = styled.div`\n\tdisplay: flex;\n\tflex-direction: column;\n\tmin-width: 0;\n\tgap: 6px;\n`;\n\nexport const DateFieldColumn = styled(FieldColumn)`\n\tflex: 1 1 0;\n`;\n\n/**\n * Same share as the date column plus the am/pm dropdown's footprint (84px\n * wide + 8px gap), so the time box itself matches the date box rather than\n * being squeezed by the dropdown sitting beside it.\n */\nexport const TimeFieldColumn = styled(FieldColumn)`\n\tflex: 1 1 ${MERIDIEM_SLOT_WIDTH + TIME_ROW_GAP}px;\n`;\n\n/**\n * The Start date / Time row.\n *\n * Aligned to the top rather than centred: the time field grows taller when its\n * validation message appears, and a centred row would shift the date field up\n * and down with it.\n */\nexport const FieldsRow = styled.div`\n\tdisplay: flex;\n\tflex-direction: row;\n\tgap: 16px;\n\twidth: 100%;\n\talign-items: flex-start;\n`;\n\n/** Wraps the date picker so its button matches the 48px input height. */\nexport const DatePickerSlot = styled.div`\n\theight: 48px;\n`;\n\n/**\n * The time box and its am/pm dropdown.\n *\n * Top-aligned rather than centred: the validation message renders inside the\n * time slot, so a centred row would push am/pm downward as the message appears.\n */\nexport const TimeInputRow = styled.div`\n\tdisplay: flex;\n\tflex-direction: row;\n\tgap: ${TIME_ROW_GAP}px;\n\talign-items: flex-start;\n`;\n\n/** The hh:mm dropdown takes the free space; am/pm is fixed beside it. */\nexport const TimeDropdownSlot = styled.div`\n\tflex: 1;\n\tmin-width: 0;\n`;\n\nexport const MeridiemDropdownSlot = styled.div`\n\tflex: 0 0 ${MERIDIEM_SLOT_WIDTH}px;\n`;\n\n/**\n * Frequency field. Fills its column, which is a DateFieldColumn so it takes the\n * same share as Start date above it — the design has both as 337px halves of the\n * 690px row, rather than a fixed 220px box that drifts as the panel resizes.\n */\nexport const FrequencyDropdownSlot = styled.div`\n\twidth: 100%;\n\tmin-width: 0;\n`;\n\n/**\n * Monthly date grid. Fixed at 337px so six CHIP_WIDTH chips and their 8px gaps\n * wrap onto a tidy 6-per-row grid rather than reflowing with the panel width.\n */\nexport const MonthDateGridSlot = styled.div`\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 8px;\n\twidth: 337px;\n\tmax-width: 100%;\n`;\n\n/**\n * Icon + text caption under a picker, for both validation errors and the\n * skipped-month note. The icon is pinned to its 16px box and aligned to the\n * first line — as a bare flex child it would stretch and open a wide gap.\n */\nexport const CaptionWithIcon = styled.div`\n\tdisplay: flex;\n\tflex-direction: row;\n\talign-items: flex-start;\n\tgap: 4px;\n\n\tsvg {\n\t\tflex: 0 0 16px;\n\t\twidth: 16px;\n\t\theight: 16px;\n\t}\n`;\n\n/** Field label row — holds the caption and its required asterisk. */\nexport const FieldLabel = styled.div`\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 2px;\n`;\n\n/** Frequency and time read in semibold inside the summary line. */\nexport const SummaryHighlight = styled.span`\n\tfont-weight: 600;\n`;\n\nexport const RequiredMark = styled.span`\n\tcolor: ${COLORS.content.negative};\n`;\n\n/** A single selectable send-mode card. */\nexport const SendModeOption = styled.div<{\n\tactive: boolean;\n\tdisabled: boolean;\n}>`\n\tbox-sizing: border-box;\n\tdisplay: flex;\n\tflex-direction: row;\n\talign-items: center;\n\tgap: 4px;\n\tpadding: 16px;\n\tflex: 1;\n\theight: 56px;\n\tborder-radius: 4px;\n\tborder: 1px solid\n\t\t${(props) =>\n\t\t\tprops.active ? COLORS.background.inverseLight : COLORS.stroke.primary};\n\tbackground: ${(props) =>\n\t\tprops.active ? COLORS.background.brandLight : COLORS.surface.standard};\n\tcursor: ${(props) => (props.disabled ? 'not-allowed' : 'pointer')};\n\topacity: ${(props) => (props.disabled ? 0.6 : 1)};\n`;\n\n/** The row of send-mode cards. */\nexport const SendModeRow = styled.div`\n\tdisplay: flex;\n\tflex-direction: row;\n\tgap: 16px;\n\twidth: 100%;\n`;\n\n/** 1px rule between the send-mode radios and the fields below. */\nexport const SectionDivider = styled.div`\n\theight: 1px;\n\twidth: 100%;\n\tbackground: ${COLORS.stroke.primary};\n`;\n\n/** \"Ends\" row wraps when the three options do not fit on one line. */\nexport const EndsRow = styled.div`\n\tdisplay: flex;\n\tflex-direction: row;\n\talign-items: center;\n\tgap: 12px;\n\tflex-wrap: wrap;\n`;\n\n/** 44px wide, 32px tall — the design's small input. */\nexport const RunCountInputWrapper = styled.div`\n\twidth: 44px;\n`;\n\nexport const EndDateWrapper = styled.div`\n\twidth: 168px;\n`;\n\nexport const UpcomingRunItem = styled.div<{ isLast: boolean }>`\n\tposition: relative;\n\tdisplay: flex;\n\tflex-direction: row;\n\talign-items: center;\n\tgap: 8px;\n\n\t/* connector spanning the 16px gap to the next run */\n\t::before {\n\t\tcontent: '';\n\t\tposition: absolute;\n\t\tleft: 4.5px;\n\t\ttop: 100%;\n\t\theight: 16px;\n\t\twidth: 1px;\n\t\tbackground: ${(props) =>\n\t\t\tprops.isLast ? 'transparent' : COLORS.stroke.brandLightAlt};\n\t}\n`;\n\nexport const UpcomingRunDot = styled.div`\n\twidth: 10px;\n\theight: 10px;\n\tborder-radius: 50%;\n\tbackground: ${COLORS.background.inverseLight};\n\tflex-shrink: 0;\n\tz-index: 1;\n`;\n\nexport const RefreshSegmentRow = styled.div`\n\tdisplay: flex;\n\tflex-direction: row;\n\talign-items: center;\n\tgap: 12px;\n\twidth: 100%;\n\tjustify-content: space-between;\n\tpadding-top: 16px;\n\tborder-top: 1px solid ${COLORS.stroke.primary};\n`;\n\nexport const RefreshSegmentCopy = styled.div`\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 4px;\n`;\n\n/** Generic vertical stack — the library cannot rely on the app's utility classes. */\nexport const Column = styled.div<{ gap?: number }>`\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: ${(props) => props.gap ?? 12}px;\n\twidth: 100%;\n`;\n\nexport const Row = styled.div<{ gap?: number }>`\n\tdisplay: flex;\n\tflex-direction: row;\n\talign-items: center;\n\tgap: ${(props) => props.gap ?? 8}px;\n`;\n"],"names":["MERIDIEM_SLOT_WIDTH","TIME_ROW_GAP","FieldColumn","styled","DateFieldColumn","TimeFieldColumn","FieldsRow","DatePickerSlot","TimeInputRow","TimeDropdownSlot","MeridiemDropdownSlot","FrequencyDropdownSlot","MonthDateGridSlot","CaptionWithIcon","FieldLabel","SummaryHighlight","RequiredMark","COLORS","SendModeOption","props","SendModeRow","SectionDivider","EndsRow","RunCountInputWrapper","EndDateWrapper","UpcomingRunItem","UpcomingRunDot","RefreshSegmentRow","RefreshSegmentCopy","Column","Row"],"mappings":";;AAIA,MAAMA,IAAsB,IACtBC,IAAe,GAMRC,IAAcC,EAAO;AAAA;AAAA;AAAA;AAAA;AAAA,GAOrBC,IAAkBD,EAAOD,CAAW;AAAA;AAAA,GASpCG,IAAkBF,EAAOD,CAAW;AAAA,aACpCF,IAAsBC,CAAY;AAAA,GAUlCK,IAAYH,EAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GASnBI,IAAiBJ,EAAO;AAAA;AAAA,GAUxBK,IAAeL,EAAO;AAAA;AAAA;AAAA,QAG3BF,CAAY;AAAA;AAAA,GAKPQ,IAAmBN,EAAO;AAAA;AAAA;AAAA,GAK1BO,IAAuBP,EAAO;AAAA,aAC9BH,CAAmB;AAAA,GAQnBW,IAAwBR,EAAO;AAAA;AAAA;AAAA,GAS/BS,IAAoBT,EAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAa3BU,IAAkBV,EAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAczBW,IAAaX,EAAO;AAAA;AAAA;AAAA;AAAA,GAOpBY,IAAmBZ,EAAO;AAAA;AAAA,GAI1Ba,IAAeb,EAAO;AAAA,UACzBc,EAAO,QAAQ,QAAQ;AAAA,GAIpBC,IAAiBf,EAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAcjC,CAACgB,MACFA,EAAM,SAASF,EAAO,WAAW,eAAeA,EAAO,OAAO,OAAO;AAAA,eACzD,CAACE,MACdA,EAAM,SAASF,EAAO,WAAW,aAAaA,EAAO,QAAQ,QAAQ;AAAA,WAC5D,CAACE,MAAWA,EAAM,WAAW,gBAAgB,SAAU;AAAA,YACtD,CAACA,MAAWA,EAAM,WAAW,MAAM,CAAE;AAAA,GAIpCC,IAAcjB,EAAO;AAAA;AAAA;AAAA;AAAA;AAAA,GAQrBkB,IAAiBlB,EAAO;AAAA;AAAA;AAAA,eAGtBc,EAAO,OAAO,OAAO;AAAA,GAIvBK,IAAUnB,EAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GASjBoB,IAAuBpB,EAAO;AAAA;AAAA,GAI9BqB,IAAiBrB,EAAO;AAAA;AAAA,GAIxBsB,IAAkBtB,EAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,gBAetB,CAACgB,MACdA,EAAM,SAAS,gBAAgBF,EAAO,OAAO,aAAa;AAAA;AAAA,GAIhDS,IAAiBvB,EAAO;AAAA;AAAA;AAAA;AAAA,eAItBc,EAAO,WAAW,YAAY;AAAA;AAAA;AAAA,GAKhCU,IAAoBxB,EAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBAQfc,EAAO,OAAO,OAAO;AAAA,GAGjCW,IAAqBzB,EAAO;AAAA;AAAA;AAAA;AAAA,GAO5B0B,IAAS1B,EAAO;AAAA;AAAA;AAAA,QAGrB,CAACgB,MAAUA,EAAM,OAAO,EAAE;AAAA;AAAA,GAIrBW,IAAM3B,EAAO;AAAA;AAAA;AAAA;AAAA,QAIlB,CAACgB,MAAUA,EAAM,OAAO,CAAC;AAAA;"}
@@ -0,0 +1,17 @@
1
+ import { default as React } from 'react';
2
+ import { RecurrenceValue } from './model';
3
+ export interface ScheduleEndPickerProps {
4
+ value: RecurrenceValue;
5
+ onChange: (patch: Partial<RecurrenceValue>) => void;
6
+ /** Earliest selectable end date — normally the series' own start date. */
7
+ minEndDate?: Date;
8
+ 'data-test'?: string;
9
+ }
10
+ /**
11
+ * "Never / After N runs / On <date>".
12
+ *
13
+ * The run-count input and the end-date picker stay mounted and go disabled with
14
+ * their mode rather than unmounting, so the row keeps its width and the controls
15
+ * do not jump as the merchant switches between them.
16
+ */
17
+ export declare const ScheduleEndPicker: React.FC<ScheduleEndPickerProps>;