@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,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const l=require("react/jsx-runtime"),a=require("./ChipSelector.styled.js"),d=e=>{const i=e.size??"medium",t=e.disabled??!1;return l.jsx(a.Chip,{type:"button",selected:e.selected,size:i,width:e.width,disabled:t,"aria-pressed":e.selected,"aria-label":e.ariaLabel??e.label,"data-test":e.dataTestId,"data-testid":"chip-selector",onClick:()=>{t||e.onSelect(e.value)},children:e.label})};exports.ChipSelector=d;
2
+ //# sourceMappingURL=ChipSelector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChipSelector.js","sources":["../../../../src/components/chip-selector/ChipSelector.tsx"],"sourcesContent":["import React from 'react';\nimport { Chip } from './ChipSelector.styled';\nimport { ChipSelectorProps } from './model';\n\n/**\n * A single compact, selectable chip.\n *\n * Most callers want ChipSelectorGroup, which manages the selection for them.\n * Use this directly only when the surrounding layout is bespoke.\n */\nexport const ChipSelector: React.FC<ChipSelectorProps> = (props) => {\n\tconst size = props.size ?? 'medium';\n\tconst isDisabled = props.disabled ?? false;\n\n\treturn (\n\t\t<Chip\n\t\t\ttype=\"button\"\n\t\t\tselected={props.selected}\n\t\t\tsize={size}\n\t\t\twidth={props.width}\n\t\t\tdisabled={isDisabled}\n\t\t\taria-pressed={props.selected}\n\t\t\taria-label={props.ariaLabel ?? props.label}\n\t\t\tdata-test={props.dataTestId}\n\t\t\tdata-testid=\"chip-selector\"\n\t\t\tonClick={() => {\n\t\t\t\tif (!isDisabled) {\n\t\t\t\t\tprops.onSelect(props.value);\n\t\t\t\t}\n\t\t\t}}\n\t\t>\n\t\t\t{props.label}\n\t\t</Chip>\n\t);\n};\n"],"names":["ChipSelector","props","size","isDisabled","jsx","Chip"],"mappings":"2JAUaA,EAA6CC,GAAU,CACnE,MAAMC,EAAOD,EAAM,MAAQ,SACrBE,EAAaF,EAAM,UAAY,GAErC,OACCG,EAAAA,IAACC,EAAAA,KAAA,CACA,KAAK,SACL,SAAUJ,EAAM,SAChB,KAAAC,EACA,MAAOD,EAAM,MACb,SAAUE,EACV,eAAcF,EAAM,SACpB,aAAYA,EAAM,WAAaA,EAAM,MACrC,YAAWA,EAAM,WACjB,cAAY,gBACZ,QAAS,IAAM,CACTE,GACJF,EAAM,SAASA,EAAM,KAAK,CAE5B,EAEC,SAAAA,EAAM,KAAA,CAAA,CAGV"}
@@ -0,0 +1,36 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("styled-components"),t=require("../../constants/Theme.js"),i=e=>e&&typeof e=="object"&&"default"in e?e:{default:e},r=i(o),d={small:"32px",medium:"48px"},n={small:"0px 8px",medium:"0px 12px"},a=r.default.button`
2
+ box-sizing: border-box;
3
+ height: ${e=>d[e.size]};
4
+ ${e=>e.width?`width: ${e.width}px;`:""}
5
+ padding: ${e=>n[e.size]};
6
+ display: flex;
7
+ align-items: center;
8
+ justify-content: center;
9
+ border-radius: 4px;
10
+ border: 1px solid
11
+ ${e=>e.selected?t.COLORS.background.inverseLight:t.COLORS.stroke.primary};
12
+ background: ${e=>e.selected?t.COLORS.background.brandLight:t.COLORS.surface.standard};
13
+ color: ${e=>e.selected?t.COLORS.content.primary:t.COLORS.content.secondary};
14
+ font-family: inherit;
15
+ font-weight: ${e=>e.selected?600:400};
16
+ font-size: 14px;
17
+ line-height: 20px;
18
+ cursor: pointer;
19
+
20
+ :disabled {
21
+ cursor: not-allowed;
22
+ color: ${t.COLORS.content.inactive};
23
+ border-color: ${t.COLORS.stroke.primary};
24
+ background: ${t.COLORS.surface.subdued};
25
+ }
26
+
27
+ :hover:not(:disabled) {
28
+ background: ${e=>e.selected?t.COLORS.background.brandLight:t.COLORS.surface.hovered};
29
+ }
30
+ `,s=r.default.div`
31
+ display: flex;
32
+ flex-direction: row;
33
+ gap: ${e=>e.gap}px;
34
+ flex-wrap: ${e=>e.wrap?"wrap":"nowrap"};
35
+ `;exports.Chip=a;exports.ChipGroup=s;
36
+ //# sourceMappingURL=ChipSelector.styled.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChipSelector.styled.js","sources":["../../../../src/components/chip-selector/ChipSelector.styled.tsx"],"sourcesContent":["import styled from 'styled-components';\nimport { COLORS } from '@src/constants/Theme';\nimport { ChipSize } from './model';\n\n/** Medium matches the 48px input height so chips align with inputs beside them. */\nconst ChipHeightMapping: Record<ChipSize, string> = {\n\tsmall: '32px',\n\tmedium: '48px',\n};\n\nconst ChipPaddingMapping: Record<ChipSize, string> = {\n\tsmall: '0px 8px',\n\tmedium: '0px 12px',\n};\n\nexport const Chip = styled.button<{\n\tselected: boolean;\n\tsize: ChipSize;\n\twidth?: number;\n}>`\n\tbox-sizing: border-box;\n\theight: ${(props) => ChipHeightMapping[props.size]};\n\t${(props) => (props.width ? `width: ${props.width}px;` : '')}\n\tpadding: ${(props) => ChipPaddingMapping[props.size]};\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\tborder-radius: 4px;\n\tborder: 1px solid\n\t\t${(props) =>\n\t\t\tprops.selected ? COLORS.background.inverseLight : COLORS.stroke.primary};\n\tbackground: ${(props) =>\n\t\tprops.selected ? COLORS.background.brandLight : COLORS.surface.standard};\n\tcolor: ${(props) =>\n\t\tprops.selected ? COLORS.content.primary : COLORS.content.secondary};\n\tfont-family: inherit;\n\tfont-weight: ${(props) => (props.selected ? 600 : 400)};\n\tfont-size: 14px;\n\tline-height: 20px;\n\tcursor: pointer;\n\n\t:disabled {\n\t\tcursor: not-allowed;\n\t\tcolor: ${COLORS.content.inactive};\n\t\tborder-color: ${COLORS.stroke.primary};\n\t\tbackground: ${COLORS.surface.subdued};\n\t}\n\n\t:hover:not(:disabled) {\n\t\tbackground: ${(props) =>\n\t\t\tprops.selected ? COLORS.background.brandLight : COLORS.surface.hovered};\n\t}\n`;\n\nexport const ChipGroup = styled.div<{ gap: number; wrap: boolean }>`\n\tdisplay: flex;\n\tflex-direction: row;\n\tgap: ${(props) => props.gap}px;\n\tflex-wrap: ${(props) => (props.wrap ? 'wrap' : 'nowrap')};\n`;\n"],"names":["ChipHeightMapping","ChipPaddingMapping","Chip","styled","props","COLORS","ChipGroup"],"mappings":"0NAKMA,EAA8C,CACnD,MAAO,OACP,OAAQ,MACT,EAEMC,EAA+C,CACpD,MAAO,UACP,OAAQ,UACT,EAEaC,EAAOC,EAAAA,QAAO;AAAA;AAAA,WAMfC,GAAUJ,EAAkBI,EAAM,IAAI,CAAC;AAAA,GAC/CA,GAAWA,EAAM,MAAQ,UAAUA,EAAM,KAAK,MAAQ,EAAG;AAAA,YAChDA,GAAUH,EAAmBG,EAAM,IAAI,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAMhDA,GACFA,EAAM,SAAWC,EAAAA,OAAO,WAAW,aAAeA,EAAAA,OAAO,OAAO,OAAO;AAAA,eAC1DD,GACdA,EAAM,SAAWC,EAAAA,OAAO,WAAW,WAAaA,EAAAA,OAAO,QAAQ,QAAQ;AAAA,UAC9DD,GACTA,EAAM,SAAWC,EAAAA,OAAO,QAAQ,QAAUA,EAAAA,OAAO,QAAQ,SAAS;AAAA;AAAA,gBAEnDD,GAAWA,EAAM,SAAW,IAAM,GAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,WAO5CC,EAAAA,OAAO,QAAQ,QAAQ;AAAA,kBAChBA,EAAAA,OAAO,OAAO,OAAO;AAAA,gBACvBA,EAAAA,OAAO,QAAQ,OAAO;AAAA;AAAA;AAAA;AAAA,gBAIrBD,GACdA,EAAM,SAAWC,EAAAA,OAAO,WAAW,WAAaA,EAAAA,OAAO,QAAQ,OAAO;AAAA;AAAA,EAI5DC,EAAYH,EAAAA,QAAO;AAAA;AAAA;AAAA,QAGvBC,GAAUA,EAAM,GAAG;AAAA,cACbA,GAAWA,EAAM,KAAO,OAAS,QAAS;AAAA"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const u=require("react/jsx-runtime"),s=require("./ChipSelector.js"),h=require("./ChipSelector.styled.js"),v=e=>{const n=e.multiSelect??!0,i=e.allowEmpty??!0,c=t=>{const a=e.value.includes(t);if(!n)return a?i?[]:e.value:[t];if(a){const l=e.value.filter(d=>d!==t);return!l.length&&!i?e.value:l}return e.options.map(l=>l.value).filter(l=>l===t||e.value.includes(l))},r=t=>{const a=c(t);a!==e.value&&e.onChange(a)};return u.jsx(h.ChipGroup,{role:"group","aria-label":e.ariaLabel,gap:e.gap??8,wrap:e.wrap??!1,"data-test":e["data-test"],"data-testid":"chip-selector-group",children:e.options.map(t=>u.jsx(s.ChipSelector,{value:t.value,label:t.label,ariaLabel:t.ariaLabel,disabled:t.disabled,selected:e.value.includes(t.value),size:e.size,width:t.fitContent?void 0:e.chipWidth,dataTestId:`${e["data-test"]??"chip"}-${t.value}`,onSelect:r},t.value))})};exports.ChipSelectorGroup=v;
2
+ //# sourceMappingURL=ChipSelectorGroup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChipSelectorGroup.js","sources":["../../../../src/components/chip-selector/ChipSelectorGroup.tsx"],"sourcesContent":["import React from 'react';\nimport { ChipSelector } from './ChipSelector';\nimport { ChipGroup } from './ChipSelector.styled';\nimport { ChipSelectorGroupProps, ChipValue } from './model';\n\n/**\n * A row or grid of compact selectable chips — weekday pickers, month-date\n * pickers, and similar cases where options are short and shown all at once.\n *\n * The group owns the add/remove logic and reports the whole next selection, so\n * callers store what they are given instead of repeating toggle code.\n */\nexport const ChipSelectorGroup: React.FC<ChipSelectorGroupProps> = (props) => {\n\tconst multiSelect = props.multiSelect ?? true;\n\tconst allowEmpty = props.allowEmpty ?? true;\n\n\tconst buildNextValue = (clicked: ChipValue): ChipValue[] => {\n\t\tconst isSelected = props.value.includes(clicked);\n\n\t\tif (!multiSelect) {\n\t\t\t// Re-picking the only selection clears it, unless a value is required.\n\t\t\tif (isSelected) {\n\t\t\t\treturn allowEmpty ? [] : props.value;\n\t\t\t}\n\t\t\treturn [clicked];\n\t\t}\n\n\t\tif (isSelected) {\n\t\t\tconst remaining = props.value.filter((value) => value !== clicked);\n\t\t\treturn !remaining.length && !allowEmpty ? props.value : remaining;\n\t\t}\n\n\t\t// Order by the options given, so the selection reads the way it is shown\n\t\t// rather than in the order the user happened to click.\n\t\treturn props.options\n\t\t\t.map((option) => option.value)\n\t\t\t.filter((value) => value === clicked || props.value.includes(value));\n\t};\n\n\tconst onChipSelected = (clicked: ChipValue) => {\n\t\tconst next = buildNextValue(clicked);\n\t\tif (next !== props.value) {\n\t\t\tprops.onChange(next);\n\t\t}\n\t};\n\n\treturn (\n\t\t<ChipGroup\n\t\t\trole=\"group\"\n\t\t\taria-label={props.ariaLabel}\n\t\t\tgap={props.gap ?? 8}\n\t\t\twrap={props.wrap ?? false}\n\t\t\tdata-test={props['data-test']}\n\t\t\tdata-testid=\"chip-selector-group\"\n\t\t>\n\t\t\t{props.options.map((option) => (\n\t\t\t\t<ChipSelector\n\t\t\t\t\tkey={option.value}\n\t\t\t\t\tvalue={option.value}\n\t\t\t\t\tlabel={option.label}\n\t\t\t\t\tariaLabel={option.ariaLabel}\n\t\t\t\t\tdisabled={option.disabled}\n\t\t\t\t\tselected={props.value.includes(option.value)}\n\t\t\t\t\tsize={props.size}\n\t\t\t\t\twidth={option.fitContent ? undefined : props.chipWidth}\n\t\t\t\t\tdataTestId={`${props['data-test'] ?? 'chip'}-${option.value}`}\n\t\t\t\t\tonSelect={onChipSelected}\n\t\t\t\t/>\n\t\t\t))}\n\t\t</ChipGroup>\n\t);\n};\n"],"names":["ChipSelectorGroup","props","multiSelect","allowEmpty","buildNextValue","clicked","isSelected","remaining","value","option","onChipSelected","next","jsx","ChipGroup","ChipSelector"],"mappings":"0LAYaA,EAAuDC,GAAU,CAC7E,MAAMC,EAAcD,EAAM,aAAe,GACnCE,EAAaF,EAAM,YAAc,GAEjCG,EAAkBC,GAAoC,CAC3D,MAAMC,EAAaL,EAAM,MAAM,SAASI,CAAO,EAE/C,GAAI,CAACH,EAEJ,OAAII,EACIH,EAAa,GAAKF,EAAM,MAEzB,CAACI,CAAO,EAGhB,GAAIC,EAAY,CACf,MAAMC,EAAYN,EAAM,MAAM,OAAQO,GAAUA,IAAUH,CAAO,EACjE,MAAO,CAACE,EAAU,QAAU,CAACJ,EAAaF,EAAM,MAAQM,CACzD,CAIA,OAAON,EAAM,QACX,IAAKQ,GAAWA,EAAO,KAAK,EAC5B,OAAQD,GAAUA,IAAUH,GAAWJ,EAAM,MAAM,SAASO,CAAK,CAAC,CACrE,EAEME,EAAkBL,GAAuB,CAC9C,MAAMM,EAAOP,EAAeC,CAAO,EAC/BM,IAASV,EAAM,OAClBA,EAAM,SAASU,CAAI,CAErB,EAEA,OACCC,EAAAA,IAACC,EAAAA,UAAA,CACA,KAAK,QACL,aAAYZ,EAAM,UAClB,IAAKA,EAAM,KAAO,EAClB,KAAMA,EAAM,MAAQ,GACpB,YAAWA,EAAM,WAAW,EAC5B,cAAY,sBAEX,SAAAA,EAAM,QAAQ,IAAKQ,GACnBG,EAAAA,IAACE,EAAAA,aAAA,CAEA,MAAOL,EAAO,MACd,MAAOA,EAAO,MACd,UAAWA,EAAO,UAClB,SAAUA,EAAO,SACjB,SAAUR,EAAM,MAAM,SAASQ,EAAO,KAAK,EAC3C,KAAMR,EAAM,KACZ,MAAOQ,EAAO,WAAa,OAAYR,EAAM,UAC7C,WAAY,GAAGA,EAAM,WAAW,GAAK,MAAM,IAAIQ,EAAO,KAAK,GAC3D,SAAUC,CAAA,EATLD,EAAO,KAAA,CAWb,CAAA,CAAA,CAGJ"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const f=require("react/jsx-runtime"),r=require("react"),K=require("../../assets/icons/chevronDown.svg.js"),I=require("./ComboBox.styled.js"),M=require("../input/Input.js"),V=(n,c)=>{const u=c.trim().toLowerCase();return u?n.filter(d=>d.value.toLowerCase().startsWith(u)):n},F=({value:n,options:c,onChange:u,validate:d,format:m,sanitize:R,filter:g=V,placeholder:k,errorMessage:E,disabled:O,onInvalidBlur:q,"data-test":L})=>{const[s,i]=r.useState(n),[h,A]=r.useState(!1),[w,B]=r.useState(-1),p=r.useRef(null),C=r.useRef(null),x=r.useRef(-1),v=r.useRef(!1),l=e=>{x.current=e,B(e)},o=e=>{v.current=e,A(e)},b=e=>d?d(e):e.trim().length>0;r.useEffect(()=>{i(e=>b(e)&&(m?m(e):e)===n?e:n)},[n]);const a=r.useMemo(()=>{const e=s.trim();return c.some(t=>t.value===e)?c:g(c,s)},[g,c,s]);r.useEffect(()=>{if(!h)return;const e=t=>{p.current?.contains(t.target)||o(!1)};return document.addEventListener("mousedown",e),()=>document.removeEventListener("mousedown",e)},[h]),r.useEffect(()=>{if(w<0)return;const e=C.current?.children[w];e instanceof HTMLElement&&e.scrollIntoView&&e.scrollIntoView({block:"nearest"})},[w]);const j=e=>{i(e.value),u(e.value),o(!1),l(-1)},S=e=>{const t=e;if(t.key==="ArrowDown"||t.key==="ArrowUp"){if(t.preventDefault(),!v.current){o(!0);return}const y=t.key==="ArrowDown"?1:-1,D=x.current+y;D<0?l(a.length-1):D>=a.length?l(0):l(D);return}if(t.key==="Enter"&&v.current&&x.current>=0){t.preventDefault(),j(a[x.current]);return}t.key==="Escape"&&o(!1)},T=()=>{if(b(s)){const e=m?m(s):s;i(e),e!==n&&u(e);return}i(n),q?.()};return f.jsxs(I.ComboBoxWrapper,{ref:p,"data-test":L,children:[f.jsx("div",{children:f.jsx(M.Input,{width:"100%",placeholder:k,value:s,isDisabled:O,errorMessage:E,state:E?"invalid":O?"disabled":"active",rightIcon:{icon:K.default,callback:()=>o(!v.current),"data-test":"combo-box-toggle"},onKeyDownEvent:S,noKeyDownChange:!0,onFocus:()=>o(!0),onChangeText:e=>{const t=R?R(e):e;i(t),o(!0),l(-1),b(t)&&u(t)},onBlur:T})}),h&&!!a.length&&f.jsx(I.OptionList,{ref:C,role:"listbox",children:a.map((e,t)=>f.jsx(I.OptionItem,{role:"option","aria-selected":e.value===n,isActive:t===w,isSelected:e.value===n,onMouseDown:y=>{y.preventDefault(),j(e)},children:e.label??e.value},e.value))})]})};exports.ComboBox=F;
2
+ //# sourceMappingURL=ComboBox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ComboBox.js","sources":["../../../../src/components/combo-box/ComboBox.tsx"],"sourcesContent":["import React, { useEffect, useMemo, useRef, useState } from 'react';\nimport DownIcon from '../../assets/icons/chevronDown.svg';\nimport { Input } from '../input';\nimport { ComboBoxWrapper, OptionItem, OptionList } from './ComboBox.styled';\nimport { ComboBoxOption, ComboBoxProps } from './model';\n\n/** Options whose value starts with what has been typed. */\nconst defaultFilter = (\n\toptions: ComboBoxOption[],\n\ttext: string,\n): ComboBoxOption[] => {\n\tconst query = text.trim().toLowerCase();\n\tif (!query) return options;\n\treturn options.filter((option) =>\n\t\toption.value.toLowerCase().startsWith(query),\n\t);\n};\n\n/**\n * A text field that can be typed into or picked from a list.\n *\n * Sits between Dropdown, whose box is not editable, and Input, which offers no\n * options. Reach for it when a field has common values worth listing but must\n * still accept anything valid the user types — a time, a duration, a currency.\n *\n * Typing is validated rather than constrained, so a half-finished entry stays in\n * the box instead of being rewritten on every keystroke; `validate` decides what\n * is worth committing and `format` tidies the text once the field is left.\n */\nexport const ComboBox: React.FC<ComboBoxProps> = ({\n\tvalue,\n\toptions,\n\tonChange,\n\tvalidate,\n\tformat,\n\tsanitize,\n\tfilter = defaultFilter,\n\tplaceholder,\n\terrorMessage,\n\tdisabled,\n\tonInvalidBlur,\n\t'data-test': dataTest,\n}) => {\n\t// What the box shows while typing. Separate from `value` so a partial entry\n\t// survives a keystroke rather than being parsed away.\n\tconst [text, setText] = useState(value);\n\tconst [isOpen, setIsOpen] = useState(false);\n\tconst [activeIndex, setActiveIndex] = useState(-1);\n\tconst wrapperRef = useRef<HTMLDivElement | null>(null);\n\tconst listRef = useRef<HTMLUListElement | null>(null);\n\t// Mirrors activeIndex for the key handler, which closes over the value from\n\t// its own render — two arrow presses in one frame would otherwise both read\n\t// the same starting index.\n\tconst activeIndexRef = useRef(-1);\n\t// Same reason as activeIndexRef: the handler must see the list state left by\n\t// the keypress before it, not the one from its own render.\n\tconst isOpenRef = useRef(false);\n\n\tconst moveActiveIndex = (next: number) => {\n\t\tactiveIndexRef.current = next;\n\t\tsetActiveIndex(next);\n\t};\n\n\tconst setListOpen = (open: boolean) => {\n\t\tisOpenRef.current = open;\n\t\tsetIsOpen(open);\n\t};\n\n\tconst isValid = (candidate: string) =>\n\t\tvalidate ? validate(candidate) : candidate.trim().length > 0;\n\n\t// Mirror committed changes from outside — a loaded value, a reset, a\n\t// recommendation — without disturbing text being typed right now.\n\tuseEffect(() => {\n\t\tsetText((prev) => {\n\t\t\tif (!isValid(prev)) return value;\n\t\t\t// Compare through `format` so text that already means the committed\n\t\t\t// value is left as typed. Without this, typing \"11:4\" is rewritten to\n\t\t\t// the formatted \"11:04\" and the next keystroke lands as \"11:045\".\n\t\t\tconst asCommitted = format ? format(prev) : prev;\n\t\t\treturn asCommitted === value ? prev : value;\n\t\t});\n\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t}, [value]);\n\n\t// An exact match still shows every option, so neighbouring values stay\n\t// reachable after picking one.\n\tconst visibleOptions = useMemo(() => {\n\t\tconst query = text.trim();\n\t\tif (options.some((option) => option.value === query)) return options;\n\t\treturn filter(options, text);\n\t}, [filter, options, text]);\n\n\tuseEffect(() => {\n\t\tif (!isOpen) return;\n\n\t\tconst handlePointerDown = (event: MouseEvent) => {\n\t\t\tif (!wrapperRef.current?.contains(event.target as Node)) {\n\t\t\t\tsetListOpen(false);\n\t\t\t}\n\t\t};\n\n\t\tdocument.addEventListener('mousedown', handlePointerDown);\n\t\treturn () => document.removeEventListener('mousedown', handlePointerDown);\n\t}, [isOpen]);\n\n\t// Keep the keyboard cursor in view when it moves past the visible rows.\n\tuseEffect(() => {\n\t\tif (activeIndex < 0) return;\n\t\tconst activeNode = listRef.current?.children[activeIndex];\n\t\t// Guarded because scrollIntoView is not implemented everywhere the library\n\t\t// renders — jsdom being the common case.\n\t\tif (activeNode instanceof HTMLElement && activeNode.scrollIntoView) {\n\t\t\tactiveNode.scrollIntoView({ block: 'nearest' });\n\t\t}\n\t}, [activeIndex]);\n\n\tconst selectOption = (option: ComboBoxOption) => {\n\t\tsetText(option.value);\n\t\tonChange(option.value);\n\t\tsetListOpen(false);\n\t\tmoveActiveIndex(-1);\n\t};\n\n\t// Typed as the DOM Event the Input hook passes; the fields read below are\n\t// KeyboardEvent's, so it is narrowed on entry.\n\tconst handleKeyDown = (nativeEvent: Event) => {\n\t\tconst event = nativeEvent as unknown as KeyboardEvent;\n\t\tif (event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n\t\t\tevent.preventDefault();\n\t\t\tif (!isOpenRef.current) {\n\t\t\t\tsetListOpen(true);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst step = event.key === 'ArrowDown' ? 1 : -1;\n\t\t\tconst next = activeIndexRef.current + step;\n\t\t\tif (next < 0) moveActiveIndex(visibleOptions.length - 1);\n\t\t\telse if (next >= visibleOptions.length) moveActiveIndex(0);\n\t\t\telse moveActiveIndex(next);\n\t\t\treturn;\n\t\t}\n\n\t\tif (\n\t\t\tevent.key === 'Enter' &&\n\t\t\tisOpenRef.current &&\n\t\t\tactiveIndexRef.current >= 0\n\t\t) {\n\t\t\tevent.preventDefault();\n\t\t\tselectOption(visibleOptions[activeIndexRef.current]);\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === 'Escape') setListOpen(false);\n\t};\n\n\tconst handleBlur = () => {\n\t\tif (isValid(text)) {\n\t\t\tconst formatted = format ? format(text) : text;\n\t\t\tsetText(formatted);\n\t\t\tif (formatted !== value) onChange(formatted);\n\t\t\treturn;\n\t\t}\n\t\t// Unusable text falls back to the last committed value.\n\t\tsetText(value);\n\t\tonInvalidBlur?.();\n\t};\n\n\treturn (\n\t\t<ComboBoxWrapper ref={wrapperRef} data-test={dataTest}>\n\t\t\t<div>\n\t\t\t\t<Input\n\t\t\t\t\twidth=\"100%\"\n\t\t\t\t\tplaceholder={placeholder}\n\t\t\t\t\tvalue={text}\n\t\t\t\t\tisDisabled={disabled}\n\t\t\t\t\terrorMessage={errorMessage}\n\t\t\t\t\tstate={errorMessage ? 'invalid' : disabled ? 'disabled' : 'active'}\n\t\t\t\t\t// Input handles its own keydown, so the arrow/Enter handling goes\n\t\t\t\t\t// through its hook rather than a wrapper that never sees the event.\n\t\t\t\t\t// Same chevron Dropdown uses, so the field reads as one rather than\n\t\t\t\t\t// looking like a plain text box that happens to suggest values.\n\t\t\t\t\trightIcon={{\n\t\t\t\t\t\ticon: DownIcon,\n\t\t\t\t\t\tcallback: () => setListOpen(!isOpenRef.current),\n\t\t\t\t\t\t'data-test': 'combo-box-toggle',\n\t\t\t\t\t}}\n\t\t\t\t\tonKeyDownEvent={handleKeyDown}\n\t\t\t\t\t// Without this Input re-fires onChangeText on every keypress, which\n\t\t\t\t\t// would re-open the list on Escape and fight the arrow keys.\n\t\t\t\t\tnoKeyDownChange\n\t\t\t\t\tonFocus={() => setListOpen(true)}\n\t\t\t\t\tonChangeText={(input: string) => {\n\t\t\t\t\t\tconst cleaned = sanitize ? sanitize(input) : input;\n\t\t\t\t\t\tsetText(cleaned);\n\t\t\t\t\t\tsetListOpen(true);\n\t\t\t\t\t\tmoveActiveIndex(-1);\n\t\t\t\t\t\tif (isValid(cleaned)) onChange(cleaned);\n\t\t\t\t\t}}\n\t\t\t\t\tonBlur={handleBlur}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t\t{isOpen && !!visibleOptions.length && (\n\t\t\t\t<OptionList ref={listRef} role=\"listbox\">\n\t\t\t\t\t{visibleOptions.map((option, index) => (\n\t\t\t\t\t\t<OptionItem\n\t\t\t\t\t\t\tkey={option.value}\n\t\t\t\t\t\t\trole=\"option\"\n\t\t\t\t\t\t\taria-selected={option.value === value}\n\t\t\t\t\t\t\tisActive={index === activeIndex}\n\t\t\t\t\t\t\tisSelected={option.value === value}\n\t\t\t\t\t\t\t// mousedown fires before the input's blur, so the click is not\n\t\t\t\t\t\t\t// lost to the field closing first.\n\t\t\t\t\t\t\tonMouseDown={(event) => {\n\t\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\t\tselectOption(option);\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{option.label ?? option.value}\n\t\t\t\t\t\t</OptionItem>\n\t\t\t\t\t))}\n\t\t\t\t</OptionList>\n\t\t\t)}\n\t\t</ComboBoxWrapper>\n\t);\n};\n\nexport default ComboBox;\n"],"names":["defaultFilter","options","text","query","option","ComboBox","value","onChange","validate","format","sanitize","filter","placeholder","errorMessage","disabled","onInvalidBlur","dataTest","setText","useState","isOpen","setIsOpen","activeIndex","setActiveIndex","wrapperRef","useRef","listRef","activeIndexRef","isOpenRef","moveActiveIndex","next","setListOpen","open","isValid","candidate","useEffect","prev","visibleOptions","useMemo","handlePointerDown","event","activeNode","selectOption","handleKeyDown","nativeEvent","step","handleBlur","formatted","jsxs","ComboBoxWrapper","jsx","Input","DownIcon","input","cleaned","OptionList","index","OptionItem"],"mappings":"4PAOMA,EAAgB,CACrBC,EACAC,IACsB,CACtB,MAAMC,EAAQD,EAAK,KAAA,EAAO,YAAA,EAC1B,OAAKC,EACEF,EAAQ,OAAQG,GACtBA,EAAO,MAAM,YAAA,EAAc,WAAWD,CAAK,CAAA,EAFzBF,CAIpB,EAaaI,EAAoC,CAAC,CACjD,MAAAC,EACA,QAAAL,EACA,SAAAM,EACA,SAAAC,EACA,OAAAC,EACA,SAAAC,EACA,OAAAC,EAASX,EACT,YAAAY,EACA,aAAAC,EACA,SAAAC,EACA,cAAAC,EACA,YAAaC,CACd,IAAM,CAGL,KAAM,CAACd,EAAMe,CAAO,EAAIC,EAAAA,SAASZ,CAAK,EAChC,CAACa,EAAQC,CAAS,EAAIF,EAAAA,SAAS,EAAK,EACpC,CAACG,EAAaC,CAAc,EAAIJ,EAAAA,SAAS,EAAE,EAC3CK,EAAaC,EAAAA,OAA8B,IAAI,EAC/CC,EAAUD,EAAAA,OAAgC,IAAI,EAI9CE,EAAiBF,EAAAA,OAAO,EAAE,EAG1BG,EAAYH,EAAAA,OAAO,EAAK,EAExBI,EAAmBC,GAAiB,CACzCH,EAAe,QAAUG,EACzBP,EAAeO,CAAI,CACpB,EAEMC,EAAeC,GAAkB,CACtCJ,EAAU,QAAUI,EACpBX,EAAUW,CAAI,CACf,EAEMC,EAAWC,GAChBzB,EAAWA,EAASyB,CAAS,EAAIA,EAAU,OAAO,OAAS,EAI5DC,EAAAA,UAAU,IAAM,CACfjB,EAASkB,GACHH,EAAQG,CAAI,IAIG1B,EAASA,EAAO0B,CAAI,EAAIA,KACrB7B,EAAQ6B,EALJ7B,CAM3B,CAEF,EAAG,CAACA,CAAK,CAAC,EAIV,MAAM8B,EAAiBC,EAAAA,QAAQ,IAAM,CACpC,MAAMlC,EAAQD,EAAK,KAAA,EACnB,OAAID,EAAQ,KAAMG,GAAWA,EAAO,QAAUD,CAAK,EAAUF,EACtDU,EAAOV,EAASC,CAAI,CAC5B,EAAG,CAACS,EAAQV,EAASC,CAAI,CAAC,EAE1BgC,EAAAA,UAAU,IAAM,CACf,GAAI,CAACf,EAAQ,OAEb,MAAMmB,EAAqBC,GAAsB,CAC3ChB,EAAW,SAAS,SAASgB,EAAM,MAAc,GACrDT,EAAY,EAAK,CAEnB,EAEA,gBAAS,iBAAiB,YAAaQ,CAAiB,EACjD,IAAM,SAAS,oBAAoB,YAAaA,CAAiB,CACzE,EAAG,CAACnB,CAAM,CAAC,EAGXe,EAAAA,UAAU,IAAM,CACf,GAAIb,EAAc,EAAG,OACrB,MAAMmB,EAAaf,EAAQ,SAAS,SAASJ,CAAW,EAGpDmB,aAAsB,aAAeA,EAAW,gBACnDA,EAAW,eAAe,CAAE,MAAO,SAAA,CAAW,CAEhD,EAAG,CAACnB,CAAW,CAAC,EAEhB,MAAMoB,EAAgBrC,GAA2B,CAChDa,EAAQb,EAAO,KAAK,EACpBG,EAASH,EAAO,KAAK,EACrB0B,EAAY,EAAK,EACjBF,EAAgB,EAAE,CACnB,EAIMc,EAAiBC,GAAuB,CAC7C,MAAMJ,EAAQI,EACd,GAAIJ,EAAM,MAAQ,aAAeA,EAAM,MAAQ,UAAW,CAEzD,GADAA,EAAM,eAAA,EACF,CAACZ,EAAU,QAAS,CACvBG,EAAY,EAAI,EAChB,MACD,CACA,MAAMc,EAAOL,EAAM,MAAQ,YAAc,EAAI,GACvCV,EAAOH,EAAe,QAAUkB,EAClCf,EAAO,EAAGD,EAAgBQ,EAAe,OAAS,CAAC,EAC9CP,GAAQO,EAAe,OAAQR,EAAgB,CAAC,IACpCC,CAAI,EACzB,MACD,CAEA,GACCU,EAAM,MAAQ,SACdZ,EAAU,SACVD,EAAe,SAAW,EACzB,CACDa,EAAM,eAAA,EACNE,EAAaL,EAAeV,EAAe,OAAO,CAAC,EACnD,MACD,CAEIa,EAAM,MAAQ,UAAUT,EAAY,EAAK,CAC9C,EAEMe,EAAa,IAAM,CACxB,GAAIb,EAAQ9B,CAAI,EAAG,CAClB,MAAM4C,EAAYrC,EAASA,EAAOP,CAAI,EAAIA,EAC1Ce,EAAQ6B,CAAS,EACbA,IAAcxC,GAAOC,EAASuC,CAAS,EAC3C,MACD,CAEA7B,EAAQX,CAAK,EACbS,IAAA,CACD,EAEA,OACCgC,EAAAA,KAACC,EAAAA,gBAAA,CAAgB,IAAKzB,EAAY,YAAWP,EAC5C,SAAA,CAAAiC,MAAC,MAAA,CACA,SAAAA,EAAAA,IAACC,EAAAA,MAAA,CACA,MAAM,OACN,YAAAtC,EACA,MAAOV,EACP,WAAYY,EACZ,aAAAD,EACA,MAAOA,EAAe,UAAYC,EAAW,WAAa,SAK1D,UAAW,CACV,KAAMqC,EAAAA,QACN,SAAU,IAAMrB,EAAY,CAACH,EAAU,OAAO,EAC9C,YAAa,kBAAA,EAEd,eAAgBe,EAGhB,gBAAe,GACf,QAAS,IAAMZ,EAAY,EAAI,EAC/B,aAAesB,GAAkB,CAChC,MAAMC,EAAU3C,EAAWA,EAAS0C,CAAK,EAAIA,EAC7CnC,EAAQoC,CAAO,EACfvB,EAAY,EAAI,EAChBF,EAAgB,EAAE,EACdI,EAAQqB,CAAO,GAAG9C,EAAS8C,CAAO,CACvC,EACA,OAAQR,CAAA,CAAA,EAEV,EACC1B,GAAU,CAAC,CAACiB,EAAe,QAC3Ba,EAAAA,IAACK,EAAAA,WAAA,CAAW,IAAK7B,EAAS,KAAK,UAC7B,SAAAW,EAAe,IAAI,CAAChC,EAAQmD,IAC5BN,EAAAA,IAACO,EAAAA,WAAA,CAEA,KAAK,SACL,gBAAepD,EAAO,QAAUE,EAChC,SAAUiD,IAAUlC,EACpB,WAAYjB,EAAO,QAAUE,EAG7B,YAAciC,GAAU,CACvBA,EAAM,eAAA,EACNE,EAAarC,CAAM,CACpB,EAEC,SAAAA,EAAO,OAASA,EAAO,KAAA,EAZnBA,EAAO,KAAA,CAcb,CAAA,CACF,CAAA,EAEF,CAEF"}
@@ -0,0 +1,33 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("styled-components"),e=require("../../constants/Theme.js"),i=t=>t&&typeof t=="object"&&"default"in t?t:{default:t},o=i(r),n=o.default.div`
2
+ position: relative;
3
+ width: 100%;
4
+ `,a=o.default.ul`
5
+ position: absolute;
6
+ top: calc(100% + 4px);
7
+ left: 0;
8
+ right: 0;
9
+ z-index: 5;
10
+ margin: 0;
11
+ padding: 4px 0;
12
+ list-style: none;
13
+ max-height: 240px;
14
+ overflow-y: auto;
15
+ background: ${e.COLORS.surface.standard};
16
+ border: 1px solid ${e.COLORS.stroke.primary};
17
+ border-radius: 4px;
18
+ box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.08);
19
+ `,s=o.default.li`
20
+ padding: 10px 12px;
21
+ cursor: pointer;
22
+ font-family: 'Inter', sans-serif;
23
+ font-size: 14px;
24
+ line-height: 20px;
25
+ color: ${t=>t.isSelected?e.COLORS.content.brand:e.COLORS.content.primary};
26
+ font-weight: ${t=>t.isSelected?600:400};
27
+ background: ${t=>t.isActive?e.COLORS.surface.hovered:"transparent"};
28
+
29
+ :hover {
30
+ background: ${e.COLORS.surface.hovered};
31
+ }
32
+ `;exports.ComboBoxWrapper=n;exports.OptionItem=s;exports.OptionList=a;
33
+ //# sourceMappingURL=ComboBox.styled.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ComboBox.styled.js","sources":["../../../../src/components/combo-box/ComboBox.styled.tsx"],"sourcesContent":["import styled from 'styled-components';\nimport { COLORS } from '@src/constants/Theme';\n\n/** Anchors the option list to the input below it. */\nexport const ComboBoxWrapper = styled.div`\n\tposition: relative;\n\twidth: 100%;\n`;\n\n/**\n * The option list. Sits above neighbouring fields — date pickers in the same\n * form commonly overlay at z-index 4, so this clears them.\n */\nexport const OptionList = styled.ul`\n\tposition: absolute;\n\ttop: calc(100% + 4px);\n\tleft: 0;\n\tright: 0;\n\tz-index: 5;\n\tmargin: 0;\n\tpadding: 4px 0;\n\tlist-style: none;\n\tmax-height: 240px;\n\toverflow-y: auto;\n\tbackground: ${COLORS.surface.standard};\n\tborder: 1px solid ${COLORS.stroke.primary};\n\tborder-radius: 4px;\n\tbox-shadow: 0px 4px 12px rgba(0, 0, 0, 0.08);\n`;\n\n/** `isActive` tracks the keyboard cursor, which is separate from selection. */\nexport const OptionItem = styled.li<{ isActive: boolean; isSelected: boolean }>`\n\tpadding: 10px 12px;\n\tcursor: pointer;\n\tfont-family: 'Inter', sans-serif;\n\tfont-size: 14px;\n\tline-height: 20px;\n\tcolor: ${(props) =>\n\t\tprops.isSelected ? COLORS.content.brand : COLORS.content.primary};\n\tfont-weight: ${(props) => (props.isSelected ? 600 : 400)};\n\tbackground: ${(props) =>\n\t\tprops.isActive ? COLORS.surface.hovered : 'transparent'};\n\n\t:hover {\n\t\tbackground: ${COLORS.surface.hovered};\n\t}\n`;\n"],"names":["ComboBoxWrapper","styled","OptionList","COLORS","OptionItem","props"],"mappings":"0NAIaA,EAAkBC,EAAAA,QAAO;AAAA;AAAA;AAAA,EASzBC,EAAaD,EAAAA,QAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,eAWlBE,EAAAA,OAAO,QAAQ,QAAQ;AAAA,qBACjBA,EAAAA,OAAO,OAAO,OAAO;AAAA;AAAA;AAAA,EAM7BC,EAAaH,EAAAA,QAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UAMtBI,GACTA,EAAM,WAAaF,EAAAA,OAAO,QAAQ,MAAQA,EAAAA,OAAO,QAAQ,OAAO;AAAA,gBACjDE,GAAWA,EAAM,WAAa,IAAM,GAAI;AAAA,eACzCA,GACdA,EAAM,SAAWF,EAAAA,OAAO,QAAQ,QAAU,aAAa;AAAA;AAAA;AAAA,gBAGzCA,EAAAA,OAAO,QAAQ,OAAO;AAAA;AAAA"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("react/jsx-runtime"),s=require("react"),m=require("react-calendar"),h=require("../../hooks/useOutside.js"),k=require("../../utils/DateUtils.js"),t=require("../../constants/Theme.js"),b=require("../../assets/icons/calendar.svg.js"),O=require("../TypographyStyle.js"),S=require("./DatePickerWrapper.styled.js"),a=require("./model.js"),w=e=>e&&typeof e=="object"&&"default"in e?e:{default:e},j=w(m),q=({val:e,onChange:d,calendarProps:y,disabled:n,pickerStyles:D,nativeID:C,maxDate:g,minDate:L,dateButtonType:o,dateButtonStyles:f})=>{const[i,c]=s.useState(!1),R=s.useRef(null),u=s.useRef(null);h.useOutside(u,()=>{c(!1)});const l=()=>e?Array.isArray(e)?e?.[0]?.toString()&&e?.[1]?.toString()?`${new Date(e?.[0]?.toString()).toLocaleDateString()}-${new Date(e?.[1]?.toString()).toLocaleDateString()}`:`${k.default.getPastDate(new Date,30).toLocaleDateString()}-${new Date().toLocaleDateString()}`:new Date(e.toString()).toLocaleDateString():new Date().toLocaleDateString();return r.jsxs(r.Fragment,{children:[r.jsxs(S.DateBtn,{id:C,ref:R,bgColor:n?t.COLORS.background.base:t.COLORS.surface.standard,borderColor:t.COLORS.stroke.primary,onClick:()=>c(!i),dateButtonType:o||a.DateButtonType.DEFAULT,style:f,children:[o===a.DateButtonType.LARGE?r.jsx(O.BodyPrimary,{style:{color:n?t.COLORS.content.inactive:t.COLORS.content.primary,flex:1},children:l()}):r.jsx(O.BodySecondary,{style:{color:n?t.COLORS.content.inactive:t.COLORS.content.primary,flex:1},children:l()}),r.jsx(b.default,{width:o===a.DateButtonType.LARGE?24:20,height:o===a.DateButtonType.LARGE?24:20,color:n?t.COLORS.content.inactive:t.COLORS.content.primary})]}),i&&!n&&r.jsx(S.PickerContainer,{ref:u,style:{...D},contentPrimary:t.COLORS.content.primary,subDued:t.COLORS.surface.subdued,brandColor:t.COLORS.background.brand,bgColor:t.COLORS.surface.standard,borderColor:t.COLORS.stroke.primary,children:r.jsx(j.default,{tileClassName:["custom__tile"],className:["custom__calendar"],onChange:p=>{d(p),c(!1)},maxDate:g,minDate:L,value:e?Array.isArray(e)?e.length===2?[new Date(e[0]),new Date(e[1])]:null:new Date(e):null,...y})})]})};exports.DatePickerWrapper=q;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("react/jsx-runtime"),b=require("date-fns"),u=require("react"),q=require("react-calendar"),w=require("../../hooks/useOutside.js"),j=require("../../utils/DateUtils.js"),t=require("../../constants/Theme.js"),x=require("../../assets/icons/calendar.svg.js"),f=require("../TypographyStyle.js"),C=require("./DatePickerWrapper.styled.js"),c=require("./model.js"),P=e=>e&&typeof e=="object"&&"default"in e?e:{default:e},A=P(q),_=({val:e,onChange:S,calendarProps:D,disabled:o,pickerStyles:R,nativeID:p,maxDate:g,minDate:m,dateButtonType:a,dateButtonStyles:L,displayFormat:l,placeholder:h})=>{const[O,i]=u.useState(!1),k=u.useRef(null),d=u.useRef(null);w.useOutside(d,()=>{i(!1)});const n=s=>l?b.format(s,l):s.toLocaleDateString(),y=()=>e?Array.isArray(e)?e?.[0]?.toString()&&e?.[1]?.toString()?`${n(new Date(e[0].toString()))}-${n(new Date(e[1].toString()))}`:`${n(j.default.getPastDate(new Date,30))}-${n(new Date)}`:n(new Date(e.toString())):h??n(new Date);return r.jsxs(r.Fragment,{children:[r.jsxs(C.DateBtn,{id:p,ref:k,bgColor:o?t.COLORS.background.base:t.COLORS.surface.standard,borderColor:t.COLORS.stroke.primary,onClick:()=>i(!O),dateButtonType:a||c.DateButtonType.DEFAULT,style:L,children:[a===c.DateButtonType.LARGE?r.jsx(f.BodyPrimary,{style:{color:o?t.COLORS.content.inactive:t.COLORS.content.primary,flex:1},children:y()}):r.jsx(f.BodySecondary,{style:{color:o?t.COLORS.content.inactive:t.COLORS.content.primary,flex:1},children:y()}),r.jsx(x.default,{width:a===c.DateButtonType.LARGE?24:20,height:a===c.DateButtonType.LARGE?24:20,color:o?t.COLORS.content.inactive:t.COLORS.content.primary})]}),O&&!o&&r.jsx(C.PickerContainer,{ref:d,style:{...R},contentPrimary:t.COLORS.content.primary,subDued:t.COLORS.surface.subdued,brandColor:t.COLORS.background.brand,bgColor:t.COLORS.surface.standard,borderColor:t.COLORS.stroke.primary,children:r.jsx(A.default,{tileClassName:["custom__tile"],className:["custom__calendar"],onChange:s=>{S(s),i(!1)},maxDate:g,minDate:m,value:e?Array.isArray(e)?e.length===2?[new Date(e[0]),new Date(e[1])]:null:new Date(e):null,...D})})]})};exports.DatePickerWrapper=_;
2
2
  //# sourceMappingURL=DatePickerWrapper.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DatePickerWrapper.js","sources":["../../../../src/components/datePicker/DatePickerWrapper.tsx"],"sourcesContent":["import React, { useRef, useState } from 'react';\nimport Calendar, { CalendarProps } from 'react-calendar';\nimport { CSSProperties } from 'styled-components';\nimport { useOutside } from '@src/hooks/useOutside';\nimport DateUtils from '@src/utils/DateUtils';\nimport { COLORS } from '@src/constants/Theme';\nimport CalendarIcon from '../../assets/icons/calendar.svg';\nimport { BodyPrimary, BodySecondary } from '../TypographyStyle';\nimport { DateBtn, PickerContainer } from './DatePickerWrapper.styled';\nimport { DateButtonType } from './model';\n\nexport const DatePickerWrapper: React.FC<{\n\tval?: Date | Date[];\n\tonChange: (val: Date | Date[]) => void;\n\tcalendarProps?: CalendarProps;\n\tpickerStyles?: CSSProperties;\n\tdateButtonStyles?: CSSProperties;\n\tnativeID?: string;\n\tdisabled?: boolean;\n\tmaxDate?: Date;\n\tminDate?: Date;\n\tdateButtonType?: DateButtonType;\n}> = ({\n\tval,\n\tonChange,\n\tcalendarProps,\n\tdisabled,\n\tpickerStyles,\n\tnativeID,\n\tmaxDate,\n\tminDate,\n\tdateButtonType,\n\tdateButtonStyles,\n}) => {\n\tconst [showPicker, setPicker] = useState(false);\n\t// const [openUpwards, setOpenUpwards] = useState(false);\n\tconst buttonRef = useRef<HTMLDivElement | null>(null);\n\tconst pickerRef = useRef<HTMLDivElement | null>(null);\n\n\tuseOutside(pickerRef, () => {\n\t\tsetPicker(false);\n\t});\n\n\t// useEffect(() => {\n\t// \tif (buttonRef.current && pickerRef.current) {\n\t// \t\tconst buttonRect = buttonRef.current.getBoundingClientRect();\n\t// \t\tconst pickerHeight = pickerRef.current.offsetHeight;\n\t// \t\tconst spaceBelow = window.innerHeight - buttonRect.bottom;\n\n\t// \t\t// If not enough space below, open upwards\n\t// \t\tsetOpenUpwards(spaceBelow < pickerHeight);\n\t// \t}\n\t// }, [showPicker]);\n\n\tconst getDisplayValue = () => {\n\t\treturn val\n\t\t\t? Array.isArray(val)\n\t\t\t\t? val?.[0]?.toString() && val?.[1]?.toString()\n\t\t\t\t\t? `${new Date(val?.[0]?.toString()).toLocaleDateString()}-${new Date(\n\t\t\t\t\t\t\tval?.[1]?.toString(),\n\t\t\t\t\t ).toLocaleDateString()}`\n\t\t\t\t\t: `${DateUtils.getPastDate(\n\t\t\t\t\t\t\tnew Date(),\n\t\t\t\t\t\t\t30,\n\t\t\t\t\t ).toLocaleDateString()}-${new Date().toLocaleDateString()}`\n\t\t\t\t: new Date(val.toString()).toLocaleDateString()\n\t\t\t: new Date().toLocaleDateString();\n\t};\n\treturn (\n\t\t<>\n\t\t\t<DateBtn\n\t\t\t\tid={nativeID}\n\t\t\t\tref={buttonRef}\n\t\t\t\tbgColor={disabled ? COLORS.background.base : COLORS.surface.standard}\n\t\t\t\tborderColor={COLORS.stroke.primary}\n\t\t\t\tonClick={() => setPicker(!showPicker)}\n\t\t\t\tdateButtonType={dateButtonType || DateButtonType.DEFAULT}\n\t\t\t\tstyle={dateButtonStyles}\n\t\t\t>\n\t\t\t\t{dateButtonType === DateButtonType.LARGE ? (\n\t\t\t\t\t<BodyPrimary\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tcolor: disabled\n\t\t\t\t\t\t\t\t? COLORS.content.inactive\n\t\t\t\t\t\t\t\t: COLORS.content.primary,\n\t\t\t\t\t\t\tflex: 1,\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{getDisplayValue()}\n\t\t\t\t\t</BodyPrimary>\n\t\t\t\t) : (\n\t\t\t\t\t<BodySecondary\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tcolor: disabled\n\t\t\t\t\t\t\t\t? COLORS.content.inactive\n\t\t\t\t\t\t\t\t: COLORS.content.primary,\n\t\t\t\t\t\t\tflex: 1,\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{getDisplayValue()}\n\t\t\t\t\t</BodySecondary>\n\t\t\t\t)}\n\t\t\t\t<CalendarIcon\n\t\t\t\t\twidth={dateButtonType === DateButtonType.LARGE ? 24 : 20}\n\t\t\t\t\theight={dateButtonType === DateButtonType.LARGE ? 24 : 20}\n\t\t\t\t\tcolor={disabled ? COLORS.content.inactive : COLORS.content.primary}\n\t\t\t\t/>\n\t\t\t</DateBtn>\n\t\t\t{showPicker && !disabled && (\n\t\t\t\t<PickerContainer\n\t\t\t\t\tref={\n\t\t\t\t\t\tpickerRef as\n\t\t\t\t\t\t\t| ((instance: HTMLDivElement | null) => void)\n\t\t\t\t\t\t\t| React.RefObject<HTMLDivElement>\n\t\t\t\t\t\t\t| null\n\t\t\t\t\t\t\t| undefined\n\t\t\t\t\t}\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\t...pickerStyles,\n\t\t\t\t\t\t// top: openUpwards ? 'auto' : 'calc(100% + 8px)',\n\t\t\t\t\t\t// bottom: openUpwards ? 'calc(100% + 8px)' : 'auto',\n\t\t\t\t\t}}\n\t\t\t\t\tcontentPrimary={COLORS.content.primary}\n\t\t\t\t\tsubDued={COLORS.surface.subdued}\n\t\t\t\t\tbrandColor={COLORS.background.brand}\n\t\t\t\t\tbgColor={COLORS.surface.standard}\n\t\t\t\t\tborderColor={COLORS.stroke.primary}\n\t\t\t\t>\n\t\t\t\t\t<Calendar\n\t\t\t\t\t\ttileClassName={['custom__tile']}\n\t\t\t\t\t\tclassName={['custom__calendar']}\n\t\t\t\t\t\tonChange={(d) => {\n\t\t\t\t\t\t\tonChange(d);\n\t\t\t\t\t\t\tsetPicker(false);\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tmaxDate={maxDate}\n\t\t\t\t\t\tminDate={minDate}\n\t\t\t\t\t\tvalue={\n\t\t\t\t\t\t\tval\n\t\t\t\t\t\t\t\t? Array.isArray(val)\n\t\t\t\t\t\t\t\t\t? val.length === 2\n\t\t\t\t\t\t\t\t\t\t? [new Date(val[0]), new Date(val[1])]\n\t\t\t\t\t\t\t\t\t\t: null\n\t\t\t\t\t\t\t\t\t: new Date(val)\n\t\t\t\t\t\t\t\t: null\n\t\t\t\t\t\t}\n\t\t\t\t\t\t{...calendarProps}\n\t\t\t\t\t/>\n\t\t\t\t</PickerContainer>\n\t\t\t)}\n\t\t</>\n\t);\n};\n"],"names":["DatePickerWrapper","val","onChange","calendarProps","disabled","pickerStyles","nativeID","maxDate","minDate","dateButtonType","dateButtonStyles","showPicker","setPicker","useState","buttonRef","useRef","pickerRef","useOutside","getDisplayValue","DateUtils","jsxs","Fragment","DateBtn","COLORS","DateButtonType","jsx","BodyPrimary","BodySecondary","CalendarIcon","PickerContainer","Calendar","d"],"mappings":"4eAWaA,EAWR,CAAC,CACL,IAAAC,EACA,SAAAC,EACA,cAAAC,EACA,SAAAC,EACA,aAAAC,EACA,SAAAC,EACA,QAAAC,EACA,QAAAC,EACA,eAAAC,EACA,iBAAAC,CACD,IAAM,CACL,KAAM,CAACC,EAAYC,CAAS,EAAIC,EAAAA,SAAS,EAAK,EAExCC,EAAYC,EAAAA,OAA8B,IAAI,EAC9CC,EAAYD,EAAAA,OAA8B,IAAI,EAEpDE,EAAAA,WAAWD,EAAW,IAAM,CAC3BJ,EAAU,EAAK,CAChB,CAAC,EAaD,MAAMM,EAAkB,IAChBjB,EACJ,MAAM,QAAQA,CAAG,EAChBA,IAAM,CAAC,GAAG,YAAcA,IAAM,CAAC,GAAG,SAAA,EACjC,GAAG,IAAI,KAAKA,IAAM,CAAC,GAAG,SAAA,CAAU,EAAE,oBAAoB,IAAI,IAAI,KAC9DA,IAAM,CAAC,GAAG,SAAA,CAAS,EACjB,mBAAA,CAAoB,GACtB,GAAGkB,EAAAA,QAAU,gBACT,KACJ,EAAA,EACE,oBAAoB,QAAQ,OAAO,oBAAoB,GAC1D,IAAI,KAAKlB,EAAI,UAAU,EAAE,qBAC1B,IAAI,KAAA,EAAO,mBAAA,EAEf,OACCmB,EAAAA,KAAAC,WAAA,CACC,SAAA,CAAAD,EAAAA,KAACE,EAAAA,QAAA,CACA,GAAIhB,EACJ,IAAKQ,EACL,QAASV,EAAWmB,SAAO,WAAW,KAAOA,EAAAA,OAAO,QAAQ,SAC5D,YAAaA,EAAAA,OAAO,OAAO,QAC3B,QAAS,IAAMX,EAAU,CAACD,CAAU,EACpC,eAAgBF,GAAkBe,EAAAA,eAAe,QACjD,MAAOd,EAEN,SAAA,CAAAD,IAAmBe,EAAAA,eAAe,MAClCC,EAAAA,IAACC,EAAAA,YAAA,CACA,MAAO,CACN,MAAOtB,EACJmB,SAAO,QAAQ,SACfA,EAAAA,OAAO,QAAQ,QAClB,KAAM,CAAA,EAGN,SAAAL,EAAA,CAAgB,CAAA,EAGlBO,EAAAA,IAACE,EAAAA,cAAA,CACA,MAAO,CACN,MAAOvB,EACJmB,SAAO,QAAQ,SACfA,EAAAA,OAAO,QAAQ,QAClB,KAAM,CAAA,EAGN,SAAAL,EAAA,CAAgB,CAAA,EAGnBO,EAAAA,IAACG,EAAAA,QAAA,CACA,MAAOnB,IAAmBe,EAAAA,eAAe,MAAQ,GAAK,GACtD,OAAQf,IAAmBe,EAAAA,eAAe,MAAQ,GAAK,GACvD,MAAOpB,EAAWmB,EAAAA,OAAO,QAAQ,SAAWA,EAAAA,OAAO,QAAQ,OAAA,CAAA,CAC5D,CAAA,CAAA,EAEAZ,GAAc,CAACP,GACfqB,EAAAA,IAACI,EAAAA,gBAAA,CACA,IACCb,EAMD,MAAO,CACN,GAAGX,CAAA,EAIJ,eAAgBkB,EAAAA,OAAO,QAAQ,QAC/B,QAASA,EAAAA,OAAO,QAAQ,QACxB,WAAYA,EAAAA,OAAO,WAAW,MAC9B,QAASA,EAAAA,OAAO,QAAQ,SACxB,YAAaA,EAAAA,OAAO,OAAO,QAE3B,SAAAE,EAAAA,IAACK,EAAAA,QAAA,CACA,cAAe,CAAC,cAAc,EAC9B,UAAW,CAAC,kBAAkB,EAC9B,SAAWC,GAAM,CAChB7B,EAAS6B,CAAC,EACVnB,EAAU,EAAK,CAChB,EACA,QAAAL,EACA,QAAAC,EACA,MACCP,EACG,MAAM,QAAQA,CAAG,EAChBA,EAAI,SAAW,EACd,CAAC,IAAI,KAAKA,EAAI,CAAC,CAAC,EAAG,IAAI,KAAKA,EAAI,CAAC,CAAC,CAAC,EACnC,KACD,IAAI,KAAKA,CAAG,EACb,KAEH,GAAGE,CAAA,CAAA,CACL,CAAA,CACD,EAEF,CAEF"}
1
+ {"version":3,"file":"DatePickerWrapper.js","sources":["../../../../src/components/datePicker/DatePickerWrapper.tsx"],"sourcesContent":["import { format as formatDate } from 'date-fns';\nimport React, { useRef, useState } from 'react';\nimport Calendar, { CalendarProps } from 'react-calendar';\nimport { CSSProperties } from 'styled-components';\nimport { useOutside } from '@src/hooks/useOutside';\nimport DateUtils from '@src/utils/DateUtils';\nimport { COLORS } from '@src/constants/Theme';\nimport CalendarIcon from '../../assets/icons/calendar.svg';\nimport { BodyPrimary, BodySecondary } from '../TypographyStyle';\nimport { DateBtn, PickerContainer } from './DatePickerWrapper.styled';\nimport { DateButtonType } from './model';\n\nexport const DatePickerWrapper: React.FC<{\n\tval?: Date | Date[];\n\tonChange: (val: Date | Date[]) => void;\n\tcalendarProps?: CalendarProps;\n\tpickerStyles?: CSSProperties;\n\tdateButtonStyles?: CSSProperties;\n\tnativeID?: string;\n\tdisabled?: boolean;\n\tmaxDate?: Date;\n\tminDate?: Date;\n\tdateButtonType?: DateButtonType;\n\t/**\n\t * date-fns format for the button label, e.g. 'dd MMM yyyy' -> \"10 Aug 2026\".\n\t * Omit to keep the locale default (toLocaleDateString).\n\t */\n\tdisplayFormat?: string;\n\t/** Shown instead of a date when `val` is empty. */\n\tplaceholder?: string;\n}> = ({\n\tval,\n\tonChange,\n\tcalendarProps,\n\tdisabled,\n\tpickerStyles,\n\tnativeID,\n\tmaxDate,\n\tminDate,\n\tdateButtonType,\n\tdateButtonStyles,\n\tdisplayFormat,\n\tplaceholder,\n}) => {\n\tconst [showPicker, setPicker] = useState(false);\n\t// const [openUpwards, setOpenUpwards] = useState(false);\n\tconst buttonRef = useRef<HTMLDivElement | null>(null);\n\tconst pickerRef = useRef<HTMLDivElement | null>(null);\n\n\tuseOutside(pickerRef, () => {\n\t\tsetPicker(false);\n\t});\n\n\t// useEffect(() => {\n\t// \tif (buttonRef.current && pickerRef.current) {\n\t// \t\tconst buttonRect = buttonRef.current.getBoundingClientRect();\n\t// \t\tconst pickerHeight = pickerRef.current.offsetHeight;\n\t// \t\tconst spaceBelow = window.innerHeight - buttonRect.bottom;\n\n\t// \t\t// If not enough space below, open upwards\n\t// \t\tsetOpenUpwards(spaceBelow < pickerHeight);\n\t// \t}\n\t// }, [showPicker]);\n\n\t/** Honours `displayFormat` when given, else the locale default. */\n\tconst formatOne = (date: Date) =>\n\t\tdisplayFormat ? formatDate(date, displayFormat) : date.toLocaleDateString();\n\n\tconst getDisplayValue = () => {\n\t\tif (!val) {\n\t\t\treturn placeholder ?? formatOne(new Date());\n\t\t}\n\n\t\tif (Array.isArray(val)) {\n\t\t\treturn val?.[0]?.toString() && val?.[1]?.toString()\n\t\t\t\t? `${formatOne(new Date(val[0].toString()))}-${formatOne(\n\t\t\t\t\t\tnew Date(val[1].toString()),\n\t\t\t\t )}`\n\t\t\t\t: `${formatOne(DateUtils.getPastDate(new Date(), 30))}-${formatOne(\n\t\t\t\t\t\tnew Date(),\n\t\t\t\t )}`;\n\t\t}\n\n\t\treturn formatOne(new Date(val.toString()));\n\t};\n\treturn (\n\t\t<>\n\t\t\t<DateBtn\n\t\t\t\tid={nativeID}\n\t\t\t\tref={buttonRef}\n\t\t\t\tbgColor={disabled ? COLORS.background.base : COLORS.surface.standard}\n\t\t\t\tborderColor={COLORS.stroke.primary}\n\t\t\t\tonClick={() => setPicker(!showPicker)}\n\t\t\t\tdateButtonType={dateButtonType || DateButtonType.DEFAULT}\n\t\t\t\tstyle={dateButtonStyles}\n\t\t\t>\n\t\t\t\t{dateButtonType === DateButtonType.LARGE ? (\n\t\t\t\t\t<BodyPrimary\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tcolor: disabled\n\t\t\t\t\t\t\t\t? COLORS.content.inactive\n\t\t\t\t\t\t\t\t: COLORS.content.primary,\n\t\t\t\t\t\t\tflex: 1,\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{getDisplayValue()}\n\t\t\t\t\t</BodyPrimary>\n\t\t\t\t) : (\n\t\t\t\t\t<BodySecondary\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tcolor: disabled\n\t\t\t\t\t\t\t\t? COLORS.content.inactive\n\t\t\t\t\t\t\t\t: COLORS.content.primary,\n\t\t\t\t\t\t\tflex: 1,\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{getDisplayValue()}\n\t\t\t\t\t</BodySecondary>\n\t\t\t\t)}\n\t\t\t\t<CalendarIcon\n\t\t\t\t\twidth={dateButtonType === DateButtonType.LARGE ? 24 : 20}\n\t\t\t\t\theight={dateButtonType === DateButtonType.LARGE ? 24 : 20}\n\t\t\t\t\tcolor={disabled ? COLORS.content.inactive : COLORS.content.primary}\n\t\t\t\t/>\n\t\t\t</DateBtn>\n\t\t\t{showPicker && !disabled && (\n\t\t\t\t<PickerContainer\n\t\t\t\t\tref={\n\t\t\t\t\t\tpickerRef as\n\t\t\t\t\t\t\t| ((instance: HTMLDivElement | null) => void)\n\t\t\t\t\t\t\t| React.RefObject<HTMLDivElement>\n\t\t\t\t\t\t\t| null\n\t\t\t\t\t\t\t| undefined\n\t\t\t\t\t}\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\t...pickerStyles,\n\t\t\t\t\t\t// top: openUpwards ? 'auto' : 'calc(100% + 8px)',\n\t\t\t\t\t\t// bottom: openUpwards ? 'calc(100% + 8px)' : 'auto',\n\t\t\t\t\t}}\n\t\t\t\t\tcontentPrimary={COLORS.content.primary}\n\t\t\t\t\tsubDued={COLORS.surface.subdued}\n\t\t\t\t\tbrandColor={COLORS.background.brand}\n\t\t\t\t\tbgColor={COLORS.surface.standard}\n\t\t\t\t\tborderColor={COLORS.stroke.primary}\n\t\t\t\t>\n\t\t\t\t\t<Calendar\n\t\t\t\t\t\ttileClassName={['custom__tile']}\n\t\t\t\t\t\tclassName={['custom__calendar']}\n\t\t\t\t\t\tonChange={(d) => {\n\t\t\t\t\t\t\tonChange(d);\n\t\t\t\t\t\t\tsetPicker(false);\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tmaxDate={maxDate}\n\t\t\t\t\t\tminDate={minDate}\n\t\t\t\t\t\tvalue={\n\t\t\t\t\t\t\tval\n\t\t\t\t\t\t\t\t? Array.isArray(val)\n\t\t\t\t\t\t\t\t\t? val.length === 2\n\t\t\t\t\t\t\t\t\t\t? [new Date(val[0]), new Date(val[1])]\n\t\t\t\t\t\t\t\t\t\t: null\n\t\t\t\t\t\t\t\t\t: new Date(val)\n\t\t\t\t\t\t\t\t: null\n\t\t\t\t\t\t}\n\t\t\t\t\t\t{...calendarProps}\n\t\t\t\t\t/>\n\t\t\t\t</PickerContainer>\n\t\t\t)}\n\t\t</>\n\t);\n};\n"],"names":["DatePickerWrapper","val","onChange","calendarProps","disabled","pickerStyles","nativeID","maxDate","minDate","dateButtonType","dateButtonStyles","displayFormat","placeholder","showPicker","setPicker","useState","buttonRef","useRef","pickerRef","useOutside","formatOne","date","formatDate","getDisplayValue","DateUtils","jsxs","Fragment","DateBtn","COLORS","DateButtonType","jsx","BodyPrimary","BodySecondary","CalendarIcon","PickerContainer","Calendar","d"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),r=require("../../constants/Theme.js"),n=require("../TypographyStyle.js"),s=require("./ScheduleBuilder.styled.js"),u=require("../switch/Switch.js"),d=({value:o,onChange:c,canRefresh:t=!0,title:i="Refresh segment before each run",caption:l="Recomputes who is in the segment before each run","data-test":h="refresh-segment-before-each-run"})=>e.jsxs(s.RefreshSegmentRow,{children:[e.jsxs(s.RefreshSegmentCopy,{children:[e.jsx(n.TitleSmall,{color:r.COLORS.content.primary,children:i}),e.jsx(n.BodyCaption,{color:r.COLORS.content.secondary,children:l})]}),e.jsx(u.Switch,{value:t&&o,disabled:!t,onValueChange:async a=>c(a),"data-test":h})]});exports.RefreshSegmentToggle=d;
2
+ //# 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":"wQA8BaA,EAA4D,CAAC,CACzE,MAAAC,EACA,SAAAC,EACA,WAAAC,EAAa,GACb,MAAAC,EAAQ,kCACR,QAAAC,EAAU,mDACV,YAAaC,EAAW,iCACzB,WACEC,oBAAA,CACA,SAAA,CAAAC,OAACC,EAAAA,mBAAA,CACA,SAAA,CAAAC,MAACC,EAAAA,WAAA,CAAW,MAAOC,EAAAA,OAAO,QAAQ,QAAU,SAAAR,EAAM,QACjDS,EAAAA,YAAA,CAAY,MAAOD,EAAAA,OAAO,QAAQ,UAAY,SAAAP,CAAA,CAAQ,CAAA,EACxD,EACAK,EAAAA,IAACI,EAAAA,OAAA,CACA,MAAOX,GAAcF,EACrB,SAAU,CAACE,EAGX,cAAe,MAAOY,GAAkBb,EAASa,CAAI,EACrD,YAAWT,CAAA,CAAA,CACZ,CAAA,CACD"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),o=require("react"),s=require("./model.js"),n=require("./ScheduleBuilder.styled.js"),F=require("./ScheduleEndPicker.js"),T=require("./ScheduleFrequencyPicker.js"),E=require("./ScheduleHelper.js"),I=require("./SendModeSelector.js"),w=require("./StartDateTimePicker.js"),f=require("./UpcomingRunsPreview.js"),B=[{value:s.SEND_MODE.SEND_NOW,label:"Send now"},{value:s.SEND_MODE.SCHEDULE,label:"Schedule"},{value:s.SEND_MODE.RECURRING,label:"Set as recurring"}],G=({sendMode:u,onSendModeChange:h,sendModeOptions:D=B,date:c,onDateChange:N,previewStartDate:d,hours:g,minutes:R,isAm:_,onTimeChange:O,onMeridiemChange:j,onTimeInvalidBlur:p,timeErrorMessage:q,minDate:P,recurrence:r,onRecurrenceChange:a,previewCount:S=E.UPCOMING_RUNS_PREVIEW_COUNT,hideUpcomingRuns:x=!1,disabled:b=!1,frequencyMenuWidth:v,children:M,recurrenceFooter:U,"data-test":C="schedule-builder"})=>{const l=u===s.SEND_MODE.RECURRING,y=!!u&&u!==s.SEND_MODE.SEND_NOW,t=o.useMemo(()=>new E.ScheduleHelper(r),[r]),m=d===void 0?c:d,i=o.useMemo(()=>l?t.computeUpcomingRuns(m,S):[],[t,m,S,l]),k=o.useMemo(()=>t.buildSummary(i),[t,i]);return e.jsxs(n.Column,{gap:16,"data-test":C,children:[e.jsx(I.SendModeSelector,{options:D,value:u,onChange:h,disabled:b,"data-test":"schedule-builder-send-mode"}),M,y&&e.jsxs(e.Fragment,{children:[e.jsx(n.SectionDivider,{}),e.jsxs(n.Column,{gap:12,children:[e.jsx(w.StartDateTimePicker,{date:c,onDateChange:N,hours:g,minutes:R,isAm:_,onTimeChange:O,onMeridiemChange:j,onTimeInvalidBlur:p,timeErrorMessage:q,dateLabel:l?"Start date":"Date",minDate:P}),l&&e.jsxs(n.Column,{gap:12,"data-test":"schedule-builder-recurrence",children:[e.jsx(T.ScheduleFrequencyPicker,{value:r??{},onChange:a,frequencyMenuWidth:v}),e.jsx(F.ScheduleEndPicker,{value:r??{},onChange:a,minEndDate:c}),!x&&e.jsx(f.UpcomingRunsPreview,{runs:i,summary:k}),U]})]})]})]})};exports.ScheduleBuilder=G;
2
+ //# 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":"uaAWMA,EAAuD,CAC5D,CAAE,MAAOC,EAAAA,UAAU,SAAU,MAAO,UAAA,EACpC,CAAE,MAAOA,EAAAA,UAAU,SAAU,MAAO,UAAA,EACpC,CAAE,MAAOA,EAAAA,UAAU,UAAW,MAAO,kBAAA,CACtC,EAwFaC,EAAkD,CAAC,CAC/D,SAAAC,EACA,iBAAAC,EACA,gBAAAC,EAAkBL,EAClB,KAAAM,EACA,aAAAC,EACA,iBAAAC,EACA,MAAAC,EACA,QAAAC,EACA,KAAAC,EACA,aAAAC,EACA,iBAAAC,EACA,kBAAAC,EACA,iBAAAC,EACA,QAAAC,EACA,WAAAC,EACA,mBAAAC,EACA,aAAAC,EAAeC,EAAAA,4BACf,iBAAAC,EAAmB,GACnB,SAAAC,EAAW,GACX,mBAAAC,EACA,SAAAC,EACA,iBAAAC,EACA,YAAaC,EAAW,kBACzB,IAAM,CACL,MAAMC,EAAcxB,IAAaF,EAAAA,UAAU,UAErC2B,EAAa,CAAC,CAACzB,GAAYA,IAAaF,EAAAA,UAAU,SAElD4B,EAASC,EAAAA,QAAQ,IAAM,IAAIC,EAAAA,eAAed,CAAU,EAAG,CAACA,CAAU,CAAC,EAOnEe,EAAcxB,IAAqB,OAAYF,EAAOE,EAEtDyB,EAAeH,EAAAA,QACpB,IACCH,EAAcE,EAAO,oBAAoBG,EAAab,CAAY,EAAI,CAAA,EACvE,CAACU,EAAQG,EAAab,EAAcQ,CAAW,CAAA,EAG1CO,EAAUJ,EAAAA,QACf,IAAMD,EAAO,aAAaI,CAAY,EACtC,CAACJ,EAAQI,CAAY,CAAA,EAGtB,OACCE,EAAAA,KAACC,EAAAA,OAAA,CAAO,IAAK,GAAI,YAAWV,EAC3B,SAAA,CAAAW,EAAAA,IAACC,EAAAA,iBAAA,CACA,QAASjC,EACT,MAAOF,EACP,SAAUC,EACV,SAAAkB,EACA,YAAU,4BAAA,CAAA,EAEVE,EACAI,GACAO,EAAAA,KAAAI,WAAA,CACC,SAAA,CAAAF,EAAAA,IAACG,EAAAA,eAAA,EAAe,EAChBL,EAAAA,KAACC,EAAAA,OAAA,CAAO,IAAK,GACZ,SAAA,CAAAC,EAAAA,IAACI,EAAAA,oBAAA,CACA,KAAAnC,EACA,aAAAC,EACA,MAAAE,EACA,QAAAC,EACA,KAAAC,EACA,aAAAC,EACA,iBAAAC,EACA,kBAAAC,EACA,iBAAAC,EAEA,UAAWY,EAAc,aAAe,OACxC,QAAAX,CAAA,CAAA,EAEAW,GACAQ,EAAAA,KAACC,EAAAA,OAAA,CAAO,IAAK,GAAI,YAAU,8BAC1B,SAAA,CAAAC,EAAAA,IAACK,EAAAA,wBAAA,CACA,MAAOzB,GAAc,CAAA,EACrB,SAAUC,EACV,mBAAAK,CAAA,CAAA,EAEDc,EAAAA,IAACM,EAAAA,kBAAA,CACA,MAAO1B,GAAc,CAAA,EACrB,SAAUC,EACV,WAAYZ,CAAA,CAAA,EAEZ,CAACe,GACDgB,EAAAA,IAACO,EAAAA,oBAAA,CAAoB,KAAMX,EAAc,QAAAC,EAAkB,EAE3DT,CAAA,CAAA,CACF,CAAA,CAAA,CAEF,CAAA,CAAA,CACD,CAAA,EAEF,CAEF"}
@@ -0,0 +1,138 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const l=require("styled-components"),i=require("../../constants/Theme.js"),a=t=>t&&typeof t=="object"&&"default"in t?t:{default:t},e=a(l),n=84,d=8,o=e.default.div`
2
+ display: flex;
3
+ flex-direction: column;
4
+ min-width: 0;
5
+ gap: 6px;
6
+ `,r=e.default(o)`
7
+ flex: 1 1 0;
8
+ `,p=e.default(o)`
9
+ flex: 1 1 ${n+d}px;
10
+ `,s=e.default.div`
11
+ display: flex;
12
+ flex-direction: row;
13
+ gap: 16px;
14
+ width: 100%;
15
+ align-items: flex-start;
16
+ `,c=e.default.div`
17
+ height: 48px;
18
+ `,f=e.default.div`
19
+ display: flex;
20
+ flex-direction: row;
21
+ gap: ${d}px;
22
+ align-items: flex-start;
23
+ `,u=e.default.div`
24
+ flex: 1;
25
+ min-width: 0;
26
+ `,x=e.default.div`
27
+ flex: 0 0 ${n}px;
28
+ `,g=e.default.div`
29
+ width: 100%;
30
+ min-width: 0;
31
+ `,m=e.default.div`
32
+ display: flex;
33
+ flex-direction: column;
34
+ gap: 8px;
35
+ width: 337px;
36
+ max-width: 100%;
37
+ `,h=e.default.div`
38
+ display: flex;
39
+ flex-direction: row;
40
+ align-items: flex-start;
41
+ gap: 4px;
42
+
43
+ svg {
44
+ flex: 0 0 16px;
45
+ width: 16px;
46
+ height: 16px;
47
+ }
48
+ `,w=e.default.div`
49
+ display: flex;
50
+ align-items: center;
51
+ gap: 2px;
52
+ `,R=e.default.span`
53
+ font-weight: 600;
54
+ `,S=e.default.span`
55
+ color: ${i.COLORS.content.negative};
56
+ `,v=e.default.div`
57
+ box-sizing: border-box;
58
+ display: flex;
59
+ flex-direction: row;
60
+ align-items: center;
61
+ gap: 4px;
62
+ padding: 16px;
63
+ flex: 1;
64
+ height: 56px;
65
+ border-radius: 4px;
66
+ border: 1px solid
67
+ ${t=>t.active?i.COLORS.background.inverseLight:i.COLORS.stroke.primary};
68
+ background: ${t=>t.active?i.COLORS.background.brandLight:i.COLORS.surface.standard};
69
+ cursor: ${t=>t.disabled?"not-allowed":"pointer"};
70
+ opacity: ${t=>t.disabled?.6:1};
71
+ `,y=e.default.div`
72
+ display: flex;
73
+ flex-direction: row;
74
+ gap: 16px;
75
+ width: 100%;
76
+ `,b=e.default.div`
77
+ height: 1px;
78
+ width: 100%;
79
+ background: ${i.COLORS.stroke.primary};
80
+ `,C=e.default.div`
81
+ display: flex;
82
+ flex-direction: row;
83
+ align-items: center;
84
+ gap: 12px;
85
+ flex-wrap: wrap;
86
+ `,O=e.default.div`
87
+ width: 44px;
88
+ `,D=e.default.div`
89
+ width: 168px;
90
+ `,L=e.default.div`
91
+ position: relative;
92
+ display: flex;
93
+ flex-direction: row;
94
+ align-items: center;
95
+ gap: 8px;
96
+
97
+ /* connector spanning the 16px gap to the next run */
98
+ ::before {
99
+ content: '';
100
+ position: absolute;
101
+ left: 4.5px;
102
+ top: 100%;
103
+ height: 16px;
104
+ width: 1px;
105
+ background: ${t=>t.isLast?"transparent":i.COLORS.stroke.brandLightAlt};
106
+ }
107
+ `,k=e.default.div`
108
+ width: 10px;
109
+ height: 10px;
110
+ border-radius: 50%;
111
+ background: ${i.COLORS.background.inverseLight};
112
+ flex-shrink: 0;
113
+ z-index: 1;
114
+ `,M=e.default.div`
115
+ display: flex;
116
+ flex-direction: row;
117
+ align-items: center;
118
+ gap: 12px;
119
+ width: 100%;
120
+ justify-content: space-between;
121
+ padding-top: 16px;
122
+ border-top: 1px solid ${i.COLORS.stroke.primary};
123
+ `,$=e.default.div`
124
+ display: flex;
125
+ flex-direction: column;
126
+ gap: 4px;
127
+ `,F=e.default.div`
128
+ display: flex;
129
+ flex-direction: column;
130
+ gap: ${t=>t.gap??12}px;
131
+ width: 100%;
132
+ `,I=e.default.div`
133
+ display: flex;
134
+ flex-direction: row;
135
+ align-items: center;
136
+ gap: ${t=>t.gap??8}px;
137
+ `;exports.CaptionWithIcon=h;exports.Column=F;exports.DateFieldColumn=r;exports.DatePickerSlot=c;exports.EndDateWrapper=D;exports.EndsRow=C;exports.FieldColumn=o;exports.FieldLabel=w;exports.FieldsRow=s;exports.FrequencyDropdownSlot=g;exports.MeridiemDropdownSlot=x;exports.MonthDateGridSlot=m;exports.RefreshSegmentCopy=$;exports.RefreshSegmentRow=M;exports.RequiredMark=S;exports.Row=I;exports.RunCountInputWrapper=O;exports.SectionDivider=b;exports.SendModeOption=v;exports.SendModeRow=y;exports.SummaryHighlight=R;exports.TimeDropdownSlot=u;exports.TimeFieldColumn=p;exports.TimeInputRow=f;exports.UpcomingRunDot=k;exports.UpcomingRunItem=L;
138
+ //# 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":"0NAIMA,EAAsB,GACtBC,EAAe,EAMRC,EAAcC,EAAAA,QAAO;AAAA;AAAA;AAAA;AAAA;AAAA,EAOrBC,EAAkBD,EAAAA,QAAOD,CAAW;AAAA;AAAA,EASpCG,EAAkBF,EAAAA,QAAOD,CAAW;AAAA,aACpCF,EAAsBC,CAAY;AAAA,EAUlCK,EAAYH,EAAAA,QAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASnBI,EAAiBJ,EAAAA,QAAO;AAAA;AAAA,EAUxBK,EAAeL,EAAAA,QAAO;AAAA;AAAA;AAAA,QAG3BF,CAAY;AAAA;AAAA,EAKPQ,EAAmBN,EAAAA,QAAO;AAAA;AAAA;AAAA,EAK1BO,EAAuBP,EAAAA,QAAO;AAAA,aAC9BH,CAAmB;AAAA,EAQnBW,EAAwBR,EAAAA,QAAO;AAAA;AAAA;AAAA,EAS/BS,EAAoBT,EAAAA,QAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAa3BU,EAAkBV,EAAAA,QAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAczBW,EAAaX,EAAAA,QAAO;AAAA;AAAA;AAAA;AAAA,EAOpBY,EAAmBZ,EAAAA,QAAO;AAAA;AAAA,EAI1Ba,EAAeb,EAAAA,QAAO;AAAA,UACzBc,EAAAA,OAAO,QAAQ,QAAQ;AAAA,EAIpBC,EAAiBf,EAAAA,QAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAchCgB,GACFA,EAAM,OAASF,EAAAA,OAAO,WAAW,aAAeA,EAAAA,OAAO,OAAO,OAAO;AAAA,eACxDE,GACdA,EAAM,OAASF,EAAAA,OAAO,WAAW,WAAaA,EAAAA,OAAO,QAAQ,QAAQ;AAAA,WAC3DE,GAAWA,EAAM,SAAW,cAAgB,SAAU;AAAA,YACrDA,GAAWA,EAAM,SAAW,GAAM,CAAE;AAAA,EAIpCC,EAAcjB,EAAAA,QAAO;AAAA;AAAA;AAAA;AAAA;AAAA,EAQrBkB,EAAiBlB,EAAAA,QAAO;AAAA;AAAA;AAAA,eAGtBc,EAAAA,OAAO,OAAO,OAAO;AAAA,EAIvBK,EAAUnB,EAAAA,QAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASjBoB,EAAuBpB,EAAAA,QAAO;AAAA;AAAA,EAI9BqB,EAAiBrB,EAAAA,QAAO;AAAA;AAAA,EAIxBsB,EAAkBtB,EAAAA,QAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,gBAerBgB,GACdA,EAAM,OAAS,cAAgBF,EAAAA,OAAO,OAAO,aAAa;AAAA;AAAA,EAIhDS,EAAiBvB,EAAAA,QAAO;AAAA;AAAA;AAAA;AAAA,eAItBc,EAAAA,OAAO,WAAW,YAAY;AAAA;AAAA;AAAA,EAKhCU,EAAoBxB,EAAAA,QAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBAQfc,EAAAA,OAAO,OAAO,OAAO;AAAA,EAGjCW,EAAqBzB,EAAAA,QAAO;AAAA;AAAA;AAAA;AAAA,EAO5B0B,EAAS1B,EAAAA,QAAO;AAAA;AAAA;AAAA,QAGpBgB,GAAUA,EAAM,KAAO,EAAE;AAAA;AAAA,EAIrBW,EAAM3B,EAAAA,QAAO;AAAA;AAAA;AAAA;AAAA,QAIjBgB,GAAUA,EAAM,KAAO,CAAC;AAAA"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const E=require("react/jsx-runtime"),a=require("../../constants/Theme.js"),N=require("../TypographyStyle.js"),e=require("./model.js"),R=require("./ScheduleBuilder.styled.js"),c=require("./ScheduleHelper.js"),d=require("../radioButton/RadioButton.js"),C=require("../input/Input.js"),u=require("../datePicker/DatePickerWrapper.js"),s=a.COLORS.background.inverseLight,O=({value:t,onChange:r,minEndDate:D,"data-test":_})=>{const n=t?.endMode??e.RECURRENCE_END_MODE.NEVER;return E.jsxs(R.FieldColumn,{"data-test":_,children:[E.jsx(R.FieldLabel,{children:E.jsx(N.BodySecondary,{color:a.COLORS.content.primary,children:"Ends"})}),E.jsxs(R.EndsRow,{children:[E.jsx(d.RadioButton,{isActive:n===e.RECURRENCE_END_MODE.NEVER,label:"Never",value:e.RECURRENCE_END_MODE.NEVER,onValueChange:()=>r({endMode:e.RECURRENCE_END_MODE.NEVER}),activeColor:s,skipSelectingOff:n===e.RECURRENCE_END_MODE.NEVER}),E.jsxs(R.Row,{gap:8,children:[E.jsx(d.RadioButton,{isActive:n===e.RECURRENCE_END_MODE.AFTER_RUNS,label:"After",value:e.RECURRENCE_END_MODE.AFTER_RUNS,onValueChange:()=>r({endMode:e.RECURRENCE_END_MODE.AFTER_RUNS}),activeColor:s,skipSelectingOff:n===e.RECURRENCE_END_MODE.AFTER_RUNS}),E.jsx(R.RunCountInputWrapper,{children:E.jsx(C.Input,{variant:"small",type:"number",placeholder:String(c.MAX_RECURRENCE_RUNS),value:t?.endAfterRuns?String(t.endAfterRuns):"",state:n===e.RECURRENCE_END_MODE.AFTER_RUNS?"none":"disabled",onChangeText:i=>{const o=i.replace(/\D/g,"");if(!o){r({endAfterRuns:void 0});return}r({endAfterRuns:Math.min(Number(o),c.MAX_RECURRENCE_RUNS)})}})}),E.jsx(N.BodySecondary,{color:a.COLORS.content.primary,children:"runs"})]}),E.jsxs(R.Row,{gap:8,children:[E.jsx(d.RadioButton,{isActive:n===e.RECURRENCE_END_MODE.ON_DATE,label:"On",value:e.RECURRENCE_END_MODE.ON_DATE,onValueChange:()=>r({endMode:e.RECURRENCE_END_MODE.ON_DATE}),activeColor:s,skipSelectingOff:n===e.RECURRENCE_END_MODE.ON_DATE}),E.jsx(R.EndDateWrapper,{children:E.jsx(u.DatePickerWrapper,{val:t?.endOnDate?new Date(t.endOnDate*1e3):void 0,disabled:n!==e.RECURRENCE_END_MODE.ON_DATE,onChange:i=>{const o=Array.isArray(i)?i[0]:i;if(!o)return;const l=new Date(o);l.setHours(23,59,59,0),r({endMode:e.RECURRENCE_END_MODE.ON_DATE,endOnDate:Math.floor(l.getTime()/1e3)})},calendarProps:{minDate:D},pickerStyles:{top:8,zIndex:4}})})]})]})]})};exports.ScheduleEndPicker=O;
2
+ //# sourceMappingURL=ScheduleEndPicker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ScheduleEndPicker.js","sources":["../../../../src/components/schedule-builder/ScheduleEndPicker.tsx"],"sourcesContent":["import React from 'react';\nimport { COLORS } from '../../constants/Theme';\nimport { DatePickerWrapper } from '../datePicker';\nimport { Input } from '../input';\nimport { RadioButton } from '../radioButton';\nimport { BodySecondary } from '../TypographyStyle';\nimport { RECURRENCE_END_MODE, RecurrenceValue } from './model';\nimport {\n\tEndDateWrapper,\n\tEndsRow,\n\tFieldColumn,\n\tFieldLabel,\n\tRow,\n\tRunCountInputWrapper,\n} from './ScheduleBuilder.styled';\nimport { MAX_RECURRENCE_RUNS } from './ScheduleHelper';\n\n/**\n * Radios in this section read brand purple when selected. The library defaults\n * to the positive green, which is not what the design shows.\n */\nconst RADIO_ACTIVE_COLOR = COLORS.background.inverseLight;\n\nexport interface ScheduleEndPickerProps {\n\tvalue: RecurrenceValue;\n\tonChange: (patch: Partial<RecurrenceValue>) => void;\n\t/** Earliest selectable end date — normally the series' own start date. */\n\tminEndDate?: Date;\n\t'data-test'?: string;\n}\n\n/**\n * \"Never / After N runs / On <date>\".\n *\n * The run-count input and the end-date picker stay mounted and go disabled with\n * their mode rather than unmounting, so the row keeps its width and the controls\n * do not jump as the merchant switches between them.\n */\nexport const ScheduleEndPicker: React.FC<ScheduleEndPickerProps> = ({\n\tvalue,\n\tonChange,\n\tminEndDate,\n\t'data-test': dataTest,\n}) => {\n\tconst endMode = value?.endMode ?? RECURRENCE_END_MODE.NEVER;\n\n\treturn (\n\t\t<FieldColumn data-test={dataTest}>\n\t\t\t<FieldLabel>\n\t\t\t\t<BodySecondary color={COLORS.content.primary}>Ends</BodySecondary>\n\t\t\t</FieldLabel>\n\t\t\t<EndsRow>\n\t\t\t\t<RadioButton\n\t\t\t\t\tisActive={endMode === RECURRENCE_END_MODE.NEVER}\n\t\t\t\t\tlabel=\"Never\"\n\t\t\t\t\tvalue={RECURRENCE_END_MODE.NEVER}\n\t\t\t\t\tonValueChange={() => onChange({ endMode: RECURRENCE_END_MODE.NEVER })}\n\t\t\t\t\tactiveColor={RADIO_ACTIVE_COLOR}\n\t\t\t\t\t// Inert only once selected — an end mode is always required, so the\n\t\t\t\t\t// active option cannot be clicked off.\n\t\t\t\t\tskipSelectingOff={endMode === RECURRENCE_END_MODE.NEVER}\n\t\t\t\t/>\n\n\t\t\t\t<Row gap={8}>\n\t\t\t\t\t<RadioButton\n\t\t\t\t\t\tisActive={endMode === RECURRENCE_END_MODE.AFTER_RUNS}\n\t\t\t\t\t\tlabel=\"After\"\n\t\t\t\t\t\tvalue={RECURRENCE_END_MODE.AFTER_RUNS}\n\t\t\t\t\t\tonValueChange={() =>\n\t\t\t\t\t\t\tonChange({ endMode: RECURRENCE_END_MODE.AFTER_RUNS })\n\t\t\t\t\t\t}\n\t\t\t\t\t\tactiveColor={RADIO_ACTIVE_COLOR}\n\t\t\t\t\t\tskipSelectingOff={endMode === RECURRENCE_END_MODE.AFTER_RUNS}\n\t\t\t\t\t/>\n\t\t\t\t\t<RunCountInputWrapper>\n\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\tvariant=\"small\"\n\t\t\t\t\t\t\ttype=\"number\"\n\t\t\t\t\t\t\tplaceholder={String(MAX_RECURRENCE_RUNS)}\n\t\t\t\t\t\t\tvalue={value?.endAfterRuns ? String(value.endAfterRuns) : ''}\n\t\t\t\t\t\t\tstate={\n\t\t\t\t\t\t\t\tendMode === RECURRENCE_END_MODE.AFTER_RUNS ? 'none' : 'disabled'\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tonChangeText={(input: string) => {\n\t\t\t\t\t\t\t\tconst digitsOnly = input.replace(/\\D/g, '');\n\t\t\t\t\t\t\t\tif (!digitsOnly) {\n\t\t\t\t\t\t\t\t\tonChange({ endAfterRuns: undefined });\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tonChange({\n\t\t\t\t\t\t\t\t\tendAfterRuns: Math.min(\n\t\t\t\t\t\t\t\t\t\tNumber(digitsOnly),\n\t\t\t\t\t\t\t\t\t\tMAX_RECURRENCE_RUNS,\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</RunCountInputWrapper>\n\t\t\t\t\t<BodySecondary color={COLORS.content.primary}>runs</BodySecondary>\n\t\t\t\t</Row>\n\n\t\t\t\t<Row gap={8}>\n\t\t\t\t\t<RadioButton\n\t\t\t\t\t\tisActive={endMode === RECURRENCE_END_MODE.ON_DATE}\n\t\t\t\t\t\tlabel=\"On\"\n\t\t\t\t\t\tvalue={RECURRENCE_END_MODE.ON_DATE}\n\t\t\t\t\t\tonValueChange={() =>\n\t\t\t\t\t\t\tonChange({ endMode: RECURRENCE_END_MODE.ON_DATE })\n\t\t\t\t\t\t}\n\t\t\t\t\t\tactiveColor={RADIO_ACTIVE_COLOR}\n\t\t\t\t\t\tskipSelectingOff={endMode === RECURRENCE_END_MODE.ON_DATE}\n\t\t\t\t\t/>\n\t\t\t\t\t<EndDateWrapper>\n\t\t\t\t\t\t<DatePickerWrapper\n\t\t\t\t\t\t\tval={\n\t\t\t\t\t\t\t\tvalue?.endOnDate ? new Date(value.endOnDate * 1000) : undefined\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tdisabled={endMode !== RECURRENCE_END_MODE.ON_DATE}\n\t\t\t\t\t\t\tonChange={(picked: Date | Date[]) => {\n\t\t\t\t\t\t\t\tconst dateValue = Array.isArray(picked) ? picked[0] : picked;\n\t\t\t\t\t\t\t\tif (!dateValue) return;\n\t\t\t\t\t\t\t\t// End of the chosen day, so a run landing that day still fires.\n\t\t\t\t\t\t\t\tconst endOfDay = new Date(dateValue);\n\t\t\t\t\t\t\t\tendOfDay.setHours(23, 59, 59, 0);\n\t\t\t\t\t\t\t\tonChange({\n\t\t\t\t\t\t\t\t\tendMode: RECURRENCE_END_MODE.ON_DATE,\n\t\t\t\t\t\t\t\t\tendOnDate: Math.floor(endOfDay.getTime() / 1000),\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\tcalendarProps={{ minDate: minEndDate }}\n\t\t\t\t\t\t\tpickerStyles={{ top: 8, zIndex: 4 }}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</EndDateWrapper>\n\t\t\t\t</Row>\n\t\t\t</EndsRow>\n\t\t</FieldColumn>\n\t);\n};\n"],"names":["RADIO_ACTIVE_COLOR","COLORS","ScheduleEndPicker","value","onChange","minEndDate","dataTest","endMode","RECURRENCE_END_MODE","jsxs","FieldColumn","jsx","FieldLabel","BodySecondary","EndsRow","RadioButton","Row","RunCountInputWrapper","Input","MAX_RECURRENCE_RUNS","input","digitsOnly","EndDateWrapper","DatePickerWrapper","picked","dateValue","endOfDay"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),n=require("../../constants/Theme.js"),u=require("../../icons/Informational/General/Info.js"),O=require("../chip-selector/ChipSelectorGroup.js"),i=require("../TypographyStyle.js"),r=require("./model.js"),t=require("./ScheduleBuilder.styled.js"),a=require("./ScheduleHelper.js"),S=require("../dropdown/Dropdown.js"),C=[{label:"Daily",value:r.RECURRENCE_FREQUENCY.DAILY},{label:"Weekly",value:r.RECURRENCE_FREQUENCY.WEEKLY},{label:"Monthly",value:r.RECURRENCE_FREQUENCY.MONTHLY}],R=[{label:"First",value:r.MONTHLY_REPEAT_OPTION.FIRST},{label:"Last",value:r.MONTHLY_REPEAT_OPTION.LAST},{label:"Custom",value:r.MONTHLY_REPEAT_OPTION.CUSTOM}],L=({value:s,onChange:d,frequencyMenuWidth:E,"data-test":x})=>{const c=new a.ScheduleHelper(s),y=c.frequency===r.RECURRENCE_FREQUENCY.WEEKLY,h=c.frequency===r.RECURRENCE_FREQUENCY.MONTHLY,j=h&&s?.monthlyRepeatOption===r.MONTHLY_REPEAT_OPTION.CUSTOM,p=a.getSkippedMonthCaption(s?.datesOfMonth),f=[...s?.datesOfMonth??[],...s?.lastDaySelected?[a.LAST_DAY_CHIP_VALUE]:[]];return e.jsxs(t.Column,{gap:12,"data-test":x,children:[e.jsxs(t.FieldsRow,{children:[e.jsxs(t.DateFieldColumn,{children:[e.jsx(t.FieldLabel,{children:e.jsx(i.BodySecondary,{color:n.COLORS.content.primary,children:"Select frequency"})}),e.jsx(t.FrequencyDropdownSlot,{children:e.jsx(S.Dropdown,{size:"default",isSearchable:!1,isMultiSelect:!1,options:C,buttonWidth:"100%",width:E||"100%",placeHolderHeight:"48px",placeHolder:"Select frequency",value:C.find(o=>o.value===c.frequency)?.label,onSelect:o=>{const l=Array.isArray(o)?o[0]:o;l?.value&&d({frequency:l.value})}})})]}),!y&&!h&&e.jsx(t.DateFieldColumn,{"aria-hidden":!0}),y&&e.jsxs(t.FieldColumn,{children:[e.jsx(t.FieldLabel,{children:e.jsx(i.BodySecondary,{color:n.COLORS.content.primary,children:"Repeat on"})}),e.jsx(O.ChipSelectorGroup,{"data-test":"recurrence-days-of-week",ariaLabel:"Repeat on",chipWidth:a.CHIP_WIDTH,options:a.DAY_CHIP_OPTIONS,value:s?.daysOfWeek??[],onChange:o=>d({daysOfWeek:o.filter(l=>typeof l=="number")})}),c.isMissingWeeklyDays&&e.jsxs(t.CaptionWithIcon,{children:[e.jsx(u.default,{size:16,color:n.COLORS.content.negative}),e.jsx(i.BodyCaption,{color:n.COLORS.content.negative,children:"Select day(s) above to send this weekly recurring"})]})]}),h&&e.jsxs(t.FieldColumn,{children:[e.jsx(t.FieldLabel,{children:e.jsx(i.BodySecondary,{color:n.COLORS.content.primary,children:"Repeat every"})}),e.jsxs(t.Row,{gap:8,children:[e.jsx(t.FrequencyDropdownSlot,{children:e.jsx(S.Dropdown,{size:"default",isSearchable:!1,isMultiSelect:!1,options:R,buttonWidth:"100%",width:"220px",placeHolderHeight:"48px",placeHolder:"Select",value:R.find(o=>o.value===s?.monthlyRepeatOption)?.label,onSelect:o=>{const l=Array.isArray(o)?o[0]:o;l?.value&&d({monthlyRepeatOption:l.value})}})}),e.jsx(i.BodySecondary,{color:n.COLORS.content.primary,children:"day of the month"})]})]})]}),j&&e.jsxs(t.MonthDateGridSlot,{children:[e.jsx(t.FieldLabel,{children:e.jsx(i.BodySecondary,{color:n.COLORS.content.primary,children:"Repeat on"})}),e.jsx(O.ChipSelectorGroup,{"data-test":"recurrence-dates-of-month",ariaLabel:"Repeat on dates",chipWidth:a.CHIP_WIDTH,options:a.DATE_CHIP_OPTIONS,size:"small",wrap:!0,value:f,onChange:o=>d({datesOfMonth:o.filter(l=>typeof l=="number"),lastDaySelected:o.includes(a.LAST_DAY_CHIP_VALUE)})}),!!p&&e.jsxs(t.CaptionWithIcon,{children:[e.jsx(u.default,{size:16,color:n.COLORS.content.secondary}),e.jsx(i.BodyCaption,{color:n.COLORS.content.secondary,children:p})]}),c.isMissingMonthlyDates&&e.jsxs(t.CaptionWithIcon,{children:[e.jsx(u.default,{size:16,color:n.COLORS.content.negative}),e.jsx(i.BodyCaption,{color:n.COLORS.content.negative,children:"Select day(s) above to send this monthly recurring"})]})]})]})};exports.ScheduleFrequencyPicker=L;
2
+ //# sourceMappingURL=ScheduleFrequencyPicker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ScheduleFrequencyPicker.js","sources":["../../../../src/components/schedule-builder/ScheduleFrequencyPicker.tsx"],"sourcesContent":["import React from 'react';\nimport { COLORS } from '../../constants/Theme';\nimport Info from '../../icons/Informational/General/Info';\nimport { ChipSelectorGroup } from '../chip-selector';\nimport { Dropdown, DropdownOption, SingleOption } from '../dropdown';\nimport { BodyCaption, BodySecondary } from '../TypographyStyle';\nimport {\n\tMONTHLY_REPEAT_OPTION,\n\tRECURRENCE_FREQUENCY,\n\tRecurrenceValue,\n} from './model';\nimport {\n\tCaptionWithIcon,\n\tColumn,\n\tDateFieldColumn,\n\tFieldColumn,\n\tFieldLabel,\n\tFieldsRow,\n\tFrequencyDropdownSlot,\n\tMonthDateGridSlot,\n\tRow,\n} from './ScheduleBuilder.styled';\nimport {\n\tCHIP_WIDTH,\n\tDATE_CHIP_OPTIONS,\n\tDAY_CHIP_OPTIONS,\n\tgetSkippedMonthCaption,\n\tLAST_DAY_CHIP_VALUE,\n\tScheduleHelper,\n} from './ScheduleHelper';\n\nconst FREQUENCY_OPTIONS: SingleOption[] = [\n\t{ label: 'Daily', value: RECURRENCE_FREQUENCY.DAILY },\n\t{ label: 'Weekly', value: RECURRENCE_FREQUENCY.WEEKLY },\n\t{ label: 'Monthly', value: RECURRENCE_FREQUENCY.MONTHLY },\n];\n\n/** \"Repeat every\" presets for a monthly recurrence. */\nconst MONTHLY_REPEAT_OPTIONS: SingleOption[] = [\n\t{ label: 'First', value: MONTHLY_REPEAT_OPTION.FIRST },\n\t{ label: 'Last', value: MONTHLY_REPEAT_OPTION.LAST },\n\t{ label: 'Custom', value: MONTHLY_REPEAT_OPTION.CUSTOM },\n];\n\nexport interface ScheduleFrequencyPickerProps {\n\tvalue: RecurrenceValue;\n\tonChange: (patch: Partial<RecurrenceValue>) => void;\n\t/**\n\t * Width of the frequency menu. Defaults to matching its button — pass a\n\t * measured width when the button sits in a narrow column and the menu should\n\t * still be readable.\n\t */\n\tfrequencyMenuWidth?: string;\n\t'data-test'?: string;\n}\n\n/**\n * Frequency, plus whichever \"Repeat on\" picker that frequency needs.\n *\n * Daily needs no picker, weekly needs day chips, monthly needs a preset dropdown\n * and — for Custom — the 1-31 date grid. All three live here so a caller does not\n * have to know which control belongs to which frequency.\n */\nexport const ScheduleFrequencyPicker: React.FC<\n\tScheduleFrequencyPickerProps\n> = ({ value, onChange, frequencyMenuWidth, 'data-test': dataTest }) => {\n\tconst helper = new ScheduleHelper(value);\n\tconst isWeekly = helper.frequency === RECURRENCE_FREQUENCY.WEEKLY;\n\tconst isMonthly = helper.frequency === RECURRENCE_FREQUENCY.MONTHLY;\n\tconst isCustomMonthly =\n\t\tisMonthly && value?.monthlyRepeatOption === MONTHLY_REPEAT_OPTION.CUSTOM;\n\n\tconst skippedMonthCaption = getSkippedMonthCaption(value?.datesOfMonth);\n\n\t/** The last-day sentinel rides alongside the numeric dates in one chip group. */\n\tconst monthlyChipValue: (string | number)[] = [\n\t\t...(value?.datesOfMonth ?? []),\n\t\t...(value?.lastDaySelected ? [LAST_DAY_CHIP_VALUE] : []),\n\t];\n\n\treturn (\n\t\t<Column gap={12} data-test={dataTest}>\n\t\t\t<FieldsRow>\n\t\t\t\t{/*\n Same flex share as the Start date column above it, per the design\n where both fields are 337px halves of the 690px row.\n */}\n\t\t\t\t<DateFieldColumn>\n\t\t\t\t\t<FieldLabel>\n\t\t\t\t\t\t<BodySecondary color={COLORS.content.primary}>\n\t\t\t\t\t\t\tSelect frequency\n\t\t\t\t\t\t</BodySecondary>\n\t\t\t\t\t</FieldLabel>\n\t\t\t\t\t<FrequencyDropdownSlot>\n\t\t\t\t\t\t<Dropdown\n\t\t\t\t\t\t\tsize=\"default\"\n\t\t\t\t\t\t\tisSearchable={false}\n\t\t\t\t\t\t\tisMultiSelect={false}\n\t\t\t\t\t\t\toptions={FREQUENCY_OPTIONS}\n\t\t\t\t\t\t\tbuttonWidth=\"100%\"\n\t\t\t\t\t\t\twidth={frequencyMenuWidth || '100%'}\n\t\t\t\t\t\t\tplaceHolderHeight=\"48px\"\n\t\t\t\t\t\t\tplaceHolder=\"Select frequency\"\n\t\t\t\t\t\t\tvalue={\n\t\t\t\t\t\t\t\tFREQUENCY_OPTIONS.find(\n\t\t\t\t\t\t\t\t\t(option) => option.value === helper.frequency,\n\t\t\t\t\t\t\t\t)?.label\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tonSelect={(\n\t\t\t\t\t\t\t\tselected: DropdownOption | DropdownOption[] | null,\n\t\t\t\t\t\t\t) => {\n\t\t\t\t\t\t\t\tconst normalized = (\n\t\t\t\t\t\t\t\t\tArray.isArray(selected) ? selected[0] : selected\n\t\t\t\t\t\t\t\t) as SingleOption | null;\n\t\t\t\t\t\t\t\tif (!normalized?.value) return;\n\t\t\t\t\t\t\t\tonChange({\n\t\t\t\t\t\t\t\t\tfrequency: normalized.value as RECURRENCE_FREQUENCY,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</FrequencyDropdownSlot>\n\t\t\t\t</DateFieldColumn>\n\t\t\t\t{/*\n Holds the other half of the row when no picker follows, so the\n frequency field stays the same width as Start date instead of\n stretching across the whole row.\n */}\n\t\t\t\t{!isWeekly && !isMonthly && <DateFieldColumn aria-hidden />}\n\t\t\t\t{isWeekly && (\n\t\t\t\t\t<FieldColumn>\n\t\t\t\t\t\t<FieldLabel>\n\t\t\t\t\t\t\t<BodySecondary color={COLORS.content.primary}>\n\t\t\t\t\t\t\t\tRepeat on\n\t\t\t\t\t\t\t</BodySecondary>\n\t\t\t\t\t\t</FieldLabel>\n\t\t\t\t\t\t<ChipSelectorGroup\n\t\t\t\t\t\t\tdata-test=\"recurrence-days-of-week\"\n\t\t\t\t\t\t\tariaLabel=\"Repeat on\"\n\t\t\t\t\t\t\tchipWidth={CHIP_WIDTH}\n\t\t\t\t\t\t\toptions={DAY_CHIP_OPTIONS}\n\t\t\t\t\t\t\tvalue={value?.daysOfWeek ?? []}\n\t\t\t\t\t\t\tonChange={(days) =>\n\t\t\t\t\t\t\t\tonChange({\n\t\t\t\t\t\t\t\t\tdaysOfWeek: days.filter(\n\t\t\t\t\t\t\t\t\t\t(day): day is number => typeof day === 'number',\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t{helper.isMissingWeeklyDays && (\n\t\t\t\t\t\t\t<CaptionWithIcon>\n\t\t\t\t\t\t\t\t<Info size={16} color={COLORS.content.negative} />\n\t\t\t\t\t\t\t\t<BodyCaption color={COLORS.content.negative}>\n\t\t\t\t\t\t\t\t\tSelect day(s) above to send this weekly recurring\n\t\t\t\t\t\t\t\t</BodyCaption>\n\t\t\t\t\t\t\t</CaptionWithIcon>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</FieldColumn>\n\t\t\t\t)}\n\t\t\t\t{isMonthly && (\n\t\t\t\t\t<FieldColumn>\n\t\t\t\t\t\t<FieldLabel>\n\t\t\t\t\t\t\t<BodySecondary color={COLORS.content.primary}>\n\t\t\t\t\t\t\t\tRepeat every\n\t\t\t\t\t\t\t</BodySecondary>\n\t\t\t\t\t\t</FieldLabel>\n\t\t\t\t\t\t<Row gap={8}>\n\t\t\t\t\t\t\t<FrequencyDropdownSlot>\n\t\t\t\t\t\t\t\t<Dropdown\n\t\t\t\t\t\t\t\t\tsize=\"default\"\n\t\t\t\t\t\t\t\t\tisSearchable={false}\n\t\t\t\t\t\t\t\t\tisMultiSelect={false}\n\t\t\t\t\t\t\t\t\toptions={MONTHLY_REPEAT_OPTIONS}\n\t\t\t\t\t\t\t\t\tbuttonWidth=\"100%\"\n\t\t\t\t\t\t\t\t\twidth=\"220px\"\n\t\t\t\t\t\t\t\t\tplaceHolderHeight=\"48px\"\n\t\t\t\t\t\t\t\t\tplaceHolder=\"Select\"\n\t\t\t\t\t\t\t\t\tvalue={\n\t\t\t\t\t\t\t\t\t\tMONTHLY_REPEAT_OPTIONS.find(\n\t\t\t\t\t\t\t\t\t\t\t(option) => option.value === value?.monthlyRepeatOption,\n\t\t\t\t\t\t\t\t\t\t)?.label\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tonSelect={(\n\t\t\t\t\t\t\t\t\t\tselected: DropdownOption | DropdownOption[] | null,\n\t\t\t\t\t\t\t\t\t) => {\n\t\t\t\t\t\t\t\t\t\tconst normalized = (\n\t\t\t\t\t\t\t\t\t\t\tArray.isArray(selected) ? selected[0] : selected\n\t\t\t\t\t\t\t\t\t\t) as SingleOption | null;\n\t\t\t\t\t\t\t\t\t\tif (!normalized?.value) return;\n\t\t\t\t\t\t\t\t\t\tonChange({\n\t\t\t\t\t\t\t\t\t\t\tmonthlyRepeatOption:\n\t\t\t\t\t\t\t\t\t\t\t\tnormalized.value as MONTHLY_REPEAT_OPTION,\n\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</FrequencyDropdownSlot>\n\t\t\t\t\t\t\t<BodySecondary color={COLORS.content.primary}>\n\t\t\t\t\t\t\t\tday of the month\n\t\t\t\t\t\t\t</BodySecondary>\n\t\t\t\t\t\t</Row>\n\t\t\t\t\t</FieldColumn>\n\t\t\t\t)}\n\t\t\t</FieldsRow>\n\n\t\t\t{isCustomMonthly && (\n\t\t\t\t<MonthDateGridSlot>\n\t\t\t\t\t<FieldLabel>\n\t\t\t\t\t\t<BodySecondary color={COLORS.content.primary}>\n\t\t\t\t\t\t\tRepeat on\n\t\t\t\t\t\t</BodySecondary>\n\t\t\t\t\t</FieldLabel>\n\t\t\t\t\t<ChipSelectorGroup\n\t\t\t\t\t\tdata-test=\"recurrence-dates-of-month\"\n\t\t\t\t\t\tariaLabel=\"Repeat on dates\"\n\t\t\t\t\t\tchipWidth={CHIP_WIDTH}\n\t\t\t\t\t\toptions={DATE_CHIP_OPTIONS}\n\t\t\t\t\t\tsize=\"small\"\n\t\t\t\t\t\twrap\n\t\t\t\t\t\tvalue={monthlyChipValue}\n\t\t\t\t\t\tonChange={(selected) =>\n\t\t\t\t\t\t\tonChange({\n\t\t\t\t\t\t\t\tdatesOfMonth: selected.filter(\n\t\t\t\t\t\t\t\t\t(item): item is number => typeof item === 'number',\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tlastDaySelected: selected.includes(LAST_DAY_CHIP_VALUE),\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\t\t\t\t\t/>\n\t\t\t\t\t{!!skippedMonthCaption && (\n\t\t\t\t\t\t<CaptionWithIcon>\n\t\t\t\t\t\t\t<Info size={16} color={COLORS.content.secondary} />\n\t\t\t\t\t\t\t<BodyCaption color={COLORS.content.secondary}>\n\t\t\t\t\t\t\t\t{skippedMonthCaption}\n\t\t\t\t\t\t\t</BodyCaption>\n\t\t\t\t\t\t</CaptionWithIcon>\n\t\t\t\t\t)}\n\t\t\t\t\t{helper.isMissingMonthlyDates && (\n\t\t\t\t\t\t<CaptionWithIcon>\n\t\t\t\t\t\t\t<Info size={16} color={COLORS.content.negative} />\n\t\t\t\t\t\t\t<BodyCaption color={COLORS.content.negative}>\n\t\t\t\t\t\t\t\tSelect day(s) above to send this monthly recurring\n\t\t\t\t\t\t\t</BodyCaption>\n\t\t\t\t\t\t</CaptionWithIcon>\n\t\t\t\t\t)}\n\t\t\t\t</MonthDateGridSlot>\n\t\t\t)}\n\t\t</Column>\n\t);\n};\n"],"names":["FREQUENCY_OPTIONS","RECURRENCE_FREQUENCY","MONTHLY_REPEAT_OPTIONS","MONTHLY_REPEAT_OPTION","ScheduleFrequencyPicker","value","onChange","frequencyMenuWidth","dataTest","helper","ScheduleHelper","isWeekly","isMonthly","isCustomMonthly","skippedMonthCaption","getSkippedMonthCaption","monthlyChipValue","LAST_DAY_CHIP_VALUE","jsxs","Column","FieldsRow","DateFieldColumn","jsx","FieldLabel","BodySecondary","COLORS","FrequencyDropdownSlot","Dropdown","option","selected","normalized","FieldColumn","ChipSelectorGroup","CHIP_WIDTH","DAY_CHIP_OPTIONS","days","day","CaptionWithIcon","Info","BodyCaption","Row","MonthDateGridSlot","DATE_CHIP_OPTIONS","item"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const d=require("date-fns"),r=require("./model.js"),R=3,N=999,f=44,_=31,D="LAST_DAY",C=1600,E=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],M=7,O=E.map((t,e)=>({value:e,label:t.charAt(0),ariaLabel:t})),g=[...Array.from({length:_},(t,e)=>({value:e+1,label:String(e+1)})),{value:D,label:"Last day of the month",fitContent:!0}],S=[1,2,3,4,5],A=[0,6],T=[1,2,3,4,5,6,0],U={29:"Skipped most Februaries.",30:"Skipped in February.",31:"Skipped in months without a 31st (Apr, Jun, Sep, Nov)."},y=t=>{if([11,12,13].includes(t%100))return`${t}th`;switch(t%10){case 1:return`${t}st`;case 2:return`${t}nd`;case 3:return`${t}rd`;default:return`${t}th`}},u=t=>t.length<=1?t[0]??"":t.length===2?`${t[0]} and ${t[1]}`:`${t.slice(0,-1).join(", ")} and ${t[t.length-1]}`,I=t=>{const e=(t??[]).map(n=>U[n]).filter(Boolean);return e.length?e.join(" "):null};class o{recurrence;constructor(e){this.recurrence=e??{}}get frequency(){return this.recurrence.frequency??r.RECURRENCE_FREQUENCY.DAILY}get endMode(){return this.recurrence.endMode??r.RECURRENCE_END_MODE.NEVER}get daysOfWeek(){return this.recurrence.daysOfWeek??[]}get datesOfMonth(){return this.recurrence.datesOfMonth??[]}get lastDaySelected(){return!!this.recurrence.lastDaySelected}get isMissingWeeklyDays(){return this.frequency===r.RECURRENCE_FREQUENCY.WEEKLY&&!this.daysOfWeek.length}get isMissingMonthlyDates(){return this.frequency===r.RECURRENCE_FREQUENCY.MONTHLY&&!this.datesOfMonth.length&&!this.lastDaySelected}get isMissingRunDays(){return this.isMissingWeeklyDays||this.isMissingMonthlyDates}addInterval(e){const n=new Date(e);return n.setDate(n.getDate()+1),n}static lastDateOfMonth(e){return new Date(e.getFullYear(),e.getMonth()+1,0).getDate()}isRunDay(e){if(this.frequency===r.RECURRENCE_FREQUENCY.WEEKLY)return this.daysOfWeek.includes(e.getDay());if(this.frequency===r.RECURRENCE_FREQUENCY.MONTHLY){const n=e.getDate();return this.datesOfMonth.includes(n)?!0:this.lastDaySelected&&n===o.lastDateOfMonth(e)}return!0}computeUpcomingRuns(e,n=R){if(!e||Number.isNaN(e.getTime()))return[];if(this.isMissingRunDays)return[];const a=[],{endAfterRuns:s}=this.recurrence,c=this.endMode===r.RECURRENCE_END_MODE.AFTER_RUNS&&typeof s=="number"&&s>0?Math.min(s,n):n,h=this.endMode===r.RECURRENCE_END_MODE.ON_DATE&&this.recurrence.endOnDate?this.recurrence.endOnDate*1e3:null;let i=new Date(e),l=0;for(;a.length<c&&l<=C&&!(h!==null&&i.getTime()>h);)this.isRunDay(i)&&a.push(new Date(i)),i=this.addInterval(i),l+=1;return a}get weeklyDayPhrase(){const e=this.daysOfWeek;if(!e.length)return"";const n=s=>e.length===s.length&&s.every(c=>e.includes(c));if(n(S))return"weekday";if(n(A))return"weekend";const a=T.filter(s=>e.includes(s)).map(s=>E[s]);return u(a)}get monthlyDatePhrase(){if(this.recurrence?.monthlyRepeatOption===r.MONTHLY_REPEAT_OPTION.FIRST)return"on the first day";const e=[...this.datesOfMonth].sort((n,a)=>n-a).map(y);return this.lastDaySelected?e.length?`on the ${u([...e,"the last day"])}`:"on the last day":e.length?`on the ${u(e)}`:""}get frequencyLabel(){switch(this.frequency){case r.RECURRENCE_FREQUENCY.WEEKLY:{const e=this.weeklyDayPhrase;return e?`every ${e}`:"weekly"}case r.RECURRENCE_FREQUENCY.MONTHLY:{const e=this.monthlyDatePhrase;return e?`${e} of every month`:"monthly"}default:return"daily"}}get endClause(){if(this.endMode===r.RECURRENCE_END_MODE.AFTER_RUNS){const e=this.recurrence.endAfterRuns;return e?` and ends after ${e} ${e===1?"run":"runs"}.`:"."}return this.endMode===r.RECURRENCE_END_MODE.ON_DATE?this.recurrence.endOnDate?` and ends on ${d.format(new Date(this.recurrence.endOnDate*1e3),"d MMM yyyy")}.`:".":" with no end date, you can cancel anytime."}buildSummary(e){return e.length?{frequencyLabel:this.frequencyLabel,timeLabel:d.format(e[0],"h:mm a"),tail:this.endClause}:null}}exports.CHIP_WIDTH=f;exports.DATE_CHIP_OPTIONS=g;exports.DAYS_IN_WEEK=M;exports.DAY_CHIP_OPTIONS=O;exports.DAY_LABELS=E;exports.LAST_DAY_CHIP_VALUE=D;exports.MAX_DATE_OF_MONTH=_;exports.MAX_RECURRENCE_RUNS=N;exports.ScheduleHelper=o;exports.UPCOMING_RUNS_PREVIEW_COUNT=R;exports.getSkippedMonthCaption=I;exports.joinList=u;exports.ordinal=y;
2
+ //# sourceMappingURL=ScheduleHelper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ScheduleHelper.js","sources":["../../../../src/components/schedule-builder/ScheduleHelper.ts"],"sourcesContent":["import { format as formatDate } from 'date-fns';\nimport { ChipOption } from '../chip-selector';\nimport {\n\tMONTHLY_REPEAT_OPTION,\n\tRECURRENCE_END_MODE,\n\tRECURRENCE_FREQUENCY,\n\tRecurrenceSummary,\n\tRecurrenceValue,\n} from './model';\n\n/** How many upcoming runs the preview shows by default. */\nexport const UPCOMING_RUNS_PREVIEW_COUNT = 3;\n\n/** Upper bound on `endAfterRuns`, matching the 3-digit input in the design. */\nexport const MAX_RECURRENCE_RUNS = 999;\n\n/**\n * Width of a single chip in the \"Repeat on\" pickers.\n *\n * Shared by the weekly day chips and the monthly date chips: both grids are\n * drawn to the same 44px square in the design, and the monthly grid's 337px\n * width assumes it, so the two cannot be sized independently.\n */\nexport const CHIP_WIDTH = 44;\n\n/** Highest date the monthly grid offers. */\nexport const MAX_DATE_OF_MONTH = 31;\n\n/** Sentinel chip value for \"Last day of the month\", which is not a date. */\nexport const LAST_DAY_CHIP_VALUE = 'LAST_DAY';\n\n/**\n * Safety bound for the day-by-day walk.\n *\n * Sized for the worst realistic case rather than the common one: three runs on\n * the 29th starting just after February in a non-leap year waits out three\n * Februaries, so roughly four years of scanning. Weekly needs at most 7 days\n * per run.\n */\nconst MAX_DAYS_SCANNED = 1600;\n\n/** Short day labels, indexed by JS day number (0 = Sunday). */\nexport const DAY_LABELS = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];\n\n/** Selecting all seven days is stored as DAILY rather than a full weekly set. */\nexport const DAYS_IN_WEEK = 7;\n\n/**\n * Chips for the weekly \"Repeat on\" picker. Only the first letter is shown, so\n * each chip carries the full day name for screen readers — S, T and S repeat.\n */\nexport const DAY_CHIP_OPTIONS: ChipOption[] = DAY_LABELS.map(\n\t(label, dayIndex) => ({\n\t\tvalue: dayIndex,\n\t\tlabel: label.charAt(0),\n\t\tariaLabel: label,\n\t}),\n);\n\n/**\n * Chips for the monthly \"Repeat on\" grid — 1 to 31, then \"Last day of the\n * month\" as an independent option rather than an alias for the 31st.\n */\nexport const DATE_CHIP_OPTIONS: ChipOption[] = [\n\t...Array.from({ length: MAX_DATE_OF_MONTH }, (_, index) => ({\n\t\tvalue: index + 1,\n\t\tlabel: String(index + 1),\n\t})),\n\t{\n\t\tvalue: LAST_DAY_CHIP_VALUE,\n\t\tlabel: 'Last day of the month',\n\t\tfitContent: true,\n\t},\n];\n\n/** Mon–Fri, used to collapse a full working week into \"every weekday\". */\nconst WEEKDAY_INDICES = [1, 2, 3, 4, 5];\n\n/** Sat–Sun, collapsed into \"every weekend\". */\nconst WEEKEND_INDICES = [0, 6];\n\n/**\n * Weekly day order for the summary. Monday-first by design, which is not the\n * JS `getDay()` order the chips are indexed by (Sunday-first).\n */\nconst SUMMARY_DAY_ORDER = [1, 2, 3, 4, 5, 6, 0];\n\n/** Dates that do not exist in every month, with the months that skip them. */\nconst SKIPPED_MONTH_CAPTIONS: Record<number, string> = {\n\t29: 'Skipped most Februaries.',\n\t30: 'Skipped in February.',\n\t31: 'Skipped in months without a 31st (Apr, Jun, Sep, Nov).',\n};\n\n/**\n * \"1st\", \"22nd\", \"13th\" — the 11/12/13 exception is why this is not a plain\n * lookup on the last digit.\n */\nexport const ordinal = (value: number): string => {\n\tif ([11, 12, 13].includes(value % 100)) return `${value}th`;\n\n\tswitch (value % 10) {\n\t\tcase 1:\n\t\t\treturn `${value}st`;\n\t\tcase 2:\n\t\t\treturn `${value}nd`;\n\t\tcase 3:\n\t\t\treturn `${value}rd`;\n\t\tdefault:\n\t\t\treturn `${value}th`;\n\t}\n};\n\n/**\n * \"Mon\", \"Mon and Tue\", \"Mon, Tue and Thu\" — no Oxford comma, and always \"and\"\n * rather than \"&\". Shared by the weekly day names and the monthly ordinals.\n */\nexport const joinList = (items: string[]): string => {\n\tif (items.length <= 1) return items[0] ?? '';\n\tif (items.length === 2) return `${items[0]} and ${items[1]}`;\n\treturn `${items.slice(0, -1).join(', ')} and ${items[items.length - 1]}`;\n};\n\n/** Caption warning that a chosen date does not exist in every month. */\nexport const getSkippedMonthCaption = (\n\tdatesOfMonth: number[] | undefined,\n): string | null => {\n\tconst captions = (datesOfMonth ?? [])\n\t\t.map((date) => SKIPPED_MONTH_CAPTIONS[date])\n\t\t.filter(Boolean);\n\treturn captions.length ? captions.join(' ') : null;\n};\n\n/**\n * Works out when a recurring campaign actually runs.\n *\n * Kept free of React so the schedule preview and the eventual publish payload\n * can both read run dates from one place.\n */\nexport class ScheduleHelper {\n\tprivate readonly recurrence: RecurrenceValue;\n\n\tconstructor(recurrence: RecurrenceValue | undefined) {\n\t\tthis.recurrence = recurrence ?? {};\n\t}\n\n\tget frequency(): RECURRENCE_FREQUENCY {\n\t\treturn this.recurrence.frequency ?? RECURRENCE_FREQUENCY.DAILY;\n\t}\n\n\tget endMode(): RECURRENCE_END_MODE {\n\t\treturn this.recurrence.endMode ?? RECURRENCE_END_MODE.NEVER;\n\t}\n\n\t/** Days a weekly recurrence repeats on, as JS day indices. */\n\tget daysOfWeek(): number[] {\n\t\treturn this.recurrence.daysOfWeek ?? [];\n\t}\n\n\t/** Dates a monthly recurrence repeats on (1–31). */\n\tget datesOfMonth(): number[] {\n\t\treturn this.recurrence.datesOfMonth ?? [];\n\t}\n\n\t/** Whether a monthly recurrence also runs on the last day of every month. */\n\tget lastDaySelected(): boolean {\n\t\treturn !!this.recurrence.lastDaySelected;\n\t}\n\n\t/** A weekly recurrence cannot run until at least one day is picked. */\n\tget isMissingWeeklyDays(): boolean {\n\t\treturn (\n\t\t\tthis.frequency === RECURRENCE_FREQUENCY.WEEKLY && !this.daysOfWeek.length\n\t\t);\n\t}\n\n\t/** A monthly recurrence needs at least one date, or the last-day option. */\n\tget isMissingMonthlyDates(): boolean {\n\t\treturn (\n\t\t\tthis.frequency === RECURRENCE_FREQUENCY.MONTHLY &&\n\t\t\t!this.datesOfMonth.length &&\n\t\t\t!this.lastDaySelected\n\t\t);\n\t}\n\n\t/** True when the current selection cannot produce any run dates. */\n\tget isMissingRunDays(): boolean {\n\t\treturn this.isMissingWeeklyDays || this.isMissingMonthlyDates;\n\t}\n\n\t/**\n\t * Advances a date by one day.\n\t *\n\t * Every frequency walks day by day so `isRunDay` decides what counts. Monthly\n\t * cannot use `setMonth`: it rolls a 31st into the following month for shorter\n\t * months (31 Jan -> 3 Mar), whereas a missing date must skip that month\n\t * outright.\n\t */\n\tprivate addInterval(date: Date): Date {\n\t\tconst next = new Date(date);\n\t\tnext.setDate(next.getDate() + 1);\n\t\treturn next;\n\t}\n\n\t/** Last calendar date of the month the given date falls in. */\n\tprivate static lastDateOfMonth(date: Date): number {\n\t\treturn new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();\n\t}\n\n\t/** Whether a candidate date is one the campaign actually runs on. */\n\tprivate isRunDay(date: Date): boolean {\n\t\tif (this.frequency === RECURRENCE_FREQUENCY.WEEKLY) {\n\t\t\treturn this.daysOfWeek.includes(date.getDay());\n\t\t}\n\n\t\tif (this.frequency === RECURRENCE_FREQUENCY.MONTHLY) {\n\t\t\tconst dayOfMonth = date.getDate();\n\t\t\tif (this.datesOfMonth.includes(dayOfMonth)) return true;\n\t\t\treturn (\n\t\t\t\tthis.lastDaySelected &&\n\t\t\t\tdayOfMonth === ScheduleHelper.lastDateOfMonth(date)\n\t\t\t);\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Next `limit` run dates from `startDate`, respecting the end rule.\n\t *\n\t * Returns fewer than `limit` when the recurrence ends first, which is what\n\t * lets the preview stop honestly instead of inventing runs.\n\t */\n\tcomputeUpcomingRuns(\n\t\tstartDate: Date | null | undefined,\n\t\tlimit: number = UPCOMING_RUNS_PREVIEW_COUNT,\n\t): Date[] {\n\t\tif (!startDate || Number.isNaN(startDate.getTime())) return [];\n\t\t// Weekly with no day picked, or monthly with no date, has no run dates yet.\n\t\tif (this.isMissingRunDays) return [];\n\n\t\tconst runs: Date[] = [];\n\n\t\t// AFTER_RUNS counts the start date as run 1, so the cap includes it.\n\t\tconst { endAfterRuns } = this.recurrence;\n\t\tconst maxRuns =\n\t\t\tthis.endMode === RECURRENCE_END_MODE.AFTER_RUNS &&\n\t\t\ttypeof endAfterRuns === 'number' &&\n\t\t\tendAfterRuns > 0\n\t\t\t\t? Math.min(endAfterRuns, limit)\n\t\t\t\t: limit;\n\n\t\tconst endDateMs =\n\t\t\tthis.endMode === RECURRENCE_END_MODE.ON_DATE && this.recurrence.endOnDate\n\t\t\t\t? this.recurrence.endOnDate * 1000\n\t\t\t\t: null;\n\n\t\tlet cursor = new Date(startDate);\n\t\t// Weekly walks a day at a time and skips days that are not selected, so\n\t\t// bound the walk rather than trusting it to land on `maxRuns` matches.\n\t\tlet daysScanned = 0;\n\n\t\twhile (runs.length < maxRuns && daysScanned <= MAX_DAYS_SCANNED) {\n\t\t\tif (endDateMs !== null && cursor.getTime() > endDateMs) break;\n\t\t\tif (this.isRunDay(cursor)) runs.push(new Date(cursor));\n\t\t\tcursor = this.addInterval(cursor);\n\t\t\tdaysScanned += 1;\n\t\t}\n\n\t\treturn runs;\n\t}\n\n\t/**\n\t * The days a weekly recurrence runs on, in Monday-first display order rather\n\t * than the Sunday-first order the chip values are indexed by.\n\t *\n\t * Mon–Fri exactly collapses to \"weekday\", Sat+Sun to \"weekend\". All seven is\n\t * not handled here — that is normalised to DAILY when the day is selected.\n\t */\n\tprivate get weeklyDayPhrase(): string {\n\t\tconst days = this.daysOfWeek;\n\t\tif (!days.length) return '';\n\n\t\tconst matchesExactly = (indices: number[]) =>\n\t\t\tdays.length === indices.length &&\n\t\t\tindices.every((day) => days.includes(day));\n\n\t\tif (matchesExactly(WEEKDAY_INDICES)) return 'weekday';\n\t\tif (matchesExactly(WEEKEND_INDICES)) return 'weekend';\n\n\t\tconst labels = SUMMARY_DAY_ORDER.filter((day) => days.includes(day)).map(\n\t\t\t(day) => DAY_LABELS[day],\n\t\t);\n\t\treturn joinList(labels);\n\t}\n\n\tprivate get monthlyDatePhrase(): string {\n\t\tif (this.recurrence?.monthlyRepeatOption === MONTHLY_REPEAT_OPTION.FIRST) {\n\t\t\treturn 'on the first day';\n\t\t}\n\n\t\tconst ordinals = [...this.datesOfMonth]\n\t\t\t.sort((left, right) => left - right)\n\t\t\t.map(ordinal);\n\n\t\tif (!this.lastDaySelected) {\n\t\t\treturn ordinals.length ? `on the ${joinList(ordinals)}` : '';\n\t\t}\n\n\t\tif (!ordinals.length) return 'on the last day';\n\t\treturn `on the ${joinList([...ordinals, 'the last day'])}`;\n\t}\n\n\t/**\n\t * The semibold phrase after \"Repeats\". Weekly and monthly name the days they\n\t * run on; daily is a plain adverb.\n\t */\n\tprivate get frequencyLabel(): string {\n\t\tswitch (this.frequency) {\n\t\t\tcase RECURRENCE_FREQUENCY.WEEKLY: {\n\t\t\t\tconst phrase = this.weeklyDayPhrase;\n\t\t\t\treturn phrase ? `every ${phrase}` : 'weekly';\n\t\t\t}\n\t\t\tcase RECURRENCE_FREQUENCY.MONTHLY: {\n\t\t\t\tconst phrase = this.monthlyDatePhrase;\n\t\t\t\treturn phrase ? `${phrase} of every month` : 'monthly';\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\treturn 'daily';\n\t\t}\n\t}\n\n\t/** The text following the time, which differs per end mode. */\n\tprivate get endClause(): string {\n\t\tif (this.endMode === RECURRENCE_END_MODE.AFTER_RUNS) {\n\t\t\tconst totalRuns = this.recurrence.endAfterRuns;\n\t\t\tif (!totalRuns) return '.';\n\t\t\treturn ` and ends after ${totalRuns} ${\n\t\t\t\ttotalRuns === 1 ? 'run' : 'runs'\n\t\t\t}.`;\n\t\t}\n\n\t\tif (this.endMode === RECURRENCE_END_MODE.ON_DATE) {\n\t\t\tif (!this.recurrence.endOnDate) return '.';\n\t\t\tconst endLabel = formatDate(\n\t\t\t\tnew Date(this.recurrence.endOnDate * 1000),\n\t\t\t\t'd MMM yyyy',\n\t\t\t);\n\t\t\treturn ` and ends on ${endLabel}.`;\n\t\t}\n\n\t\treturn ' with no end date, you can cancel anytime.';\n\t}\n\n\t/**\n\t * Summary shown under the upcoming runs, split so the frequency and time can\n\t * be rendered in semibold as the design shows:\n\t * \"Repeats **daily** at **10:00 AM** with no end date, you can cancel anytime.\"\n\t */\n\tbuildSummary(runs: Date[]): RecurrenceSummary | null {\n\t\tif (!runs.length) return null;\n\n\t\treturn {\n\t\t\tfrequencyLabel: this.frequencyLabel,\n\t\t\ttimeLabel: formatDate(runs[0], 'h:mm a'),\n\t\t\ttail: this.endClause,\n\t\t};\n\t}\n}\n"],"names":["UPCOMING_RUNS_PREVIEW_COUNT","MAX_RECURRENCE_RUNS","CHIP_WIDTH","MAX_DATE_OF_MONTH","LAST_DAY_CHIP_VALUE","MAX_DAYS_SCANNED","DAY_LABELS","DAYS_IN_WEEK","DAY_CHIP_OPTIONS","label","dayIndex","DATE_CHIP_OPTIONS","_","index","WEEKDAY_INDICES","WEEKEND_INDICES","SUMMARY_DAY_ORDER","SKIPPED_MONTH_CAPTIONS","ordinal","value","joinList","items","getSkippedMonthCaption","datesOfMonth","captions","date","ScheduleHelper","recurrence","RECURRENCE_FREQUENCY","RECURRENCE_END_MODE","next","dayOfMonth","startDate","limit","runs","endAfterRuns","maxRuns","endDateMs","cursor","daysScanned","days","matchesExactly","indices","day","labels","MONTHLY_REPEAT_OPTION","ordinals","left","right","phrase","totalRuns","formatDate"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("react/jsx-runtime"),c=require("../../constants/Theme.js"),r=require("./ScheduleBuilder.styled.js"),i=require("../radioButton/RadioButton.js"),n=c.COLORS.background.inverseLight,v=({options:s,value:d,onChange:t,disabled:l=!1,"data-test":u})=>a.jsx(r.SendModeRow,{"data-test":u,children:s.map(e=>a.jsx(r.SendModeOption,{active:d===e.value,disabled:l||!!e.disabled,"data-test":`send-mode-${e.value}`,onClick:()=>{l||e.disabled||t(e.value)},children:a.jsx(i.RadioButton,{isActive:d===e.value,isDisabled:l||!!e.disabled,label:e.label,value:e.value,onValueChange:()=>{l||e.disabled||t(e.value)},alwaysBold:!0,activeColor:n,skipSelectingOff:!0})},e.value))});exports.SendModeSelector=v;
2
+ //# sourceMappingURL=SendModeSelector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SendModeSelector.js","sources":["../../../../src/components/schedule-builder/SendModeSelector.tsx"],"sourcesContent":["import { COLORS } from '../../constants/Theme';\nimport { RadioButton } from '../radioButton';\nimport { SendModeOption, SendModeRow } from './ScheduleBuilder.styled';\n\n/** The purple of the selected radio, which is not the default brand colour. */\nconst RADIO_ACTIVE_COLOR = COLORS.background.inverseLight;\n\nexport interface SendModeItem<T extends string = string> {\n\tvalue: T;\n\tlabel: string;\n\t/**\n\t * Greys out this mode while leaving the others usable.\n\t *\n\t * Disabled rather than removed so the mode still reads as something the\n\t * product offers — a merchant who cannot use it here should see that it\n\t * exists, not wonder where it went.\n\t */\n\tdisabled?: boolean;\n}\n\nexport interface SendModeSelectorProps<T extends string = string> {\n\toptions: SendModeItem<T>[];\n\tvalue?: T;\n\tonChange: (value: T) => void;\n\tdisabled?: boolean;\n\t'data-test'?: string;\n}\n\n/**\n * The row of \"Send now / Schedule / Set as recurring\" cards.\n *\n * The whole card is the hit target, not just the radio — the radio's own\n * `onValueChange` fires too, so both routes land on the same handler.\n *\n * Options are passed in rather than hardcoded: the modes a screen offers are its\n * own business, and a caller with only two of them should not get a dead third.\n */\nexport const SendModeSelector = <T extends string = string>({\n\toptions,\n\tvalue,\n\tonChange,\n\tdisabled = false,\n\t'data-test': dataTest,\n}: SendModeSelectorProps<T>) => (\n\t<SendModeRow data-test={dataTest}>\n\t\t{options.map((option) => (\n\t\t\t<SendModeOption\n\t\t\t\tkey={option.value}\n\t\t\t\tactive={value === option.value}\n\t\t\t\tdisabled={disabled || !!option.disabled}\n\t\t\t\tdata-test={`send-mode-${option.value}`}\n\t\t\t\tonClick={() => {\n\t\t\t\t\tif (disabled || option.disabled) return;\n\t\t\t\t\tonChange(option.value);\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<RadioButton\n\t\t\t\t\tisActive={value === option.value}\n\t\t\t\t\tisDisabled={disabled || !!option.disabled}\n\t\t\t\t\tlabel={option.label}\n\t\t\t\t\tvalue={option.value}\n\t\t\t\t\tonValueChange={() => {\n\t\t\t\t\t\tif (disabled || option.disabled) return;\n\t\t\t\t\t\tonChange(option.value);\n\t\t\t\t\t}}\n\t\t\t\t\talwaysBold\n\t\t\t\t\tactiveColor={RADIO_ACTIVE_COLOR}\n\t\t\t\t\tskipSelectingOff\n\t\t\t\t/>\n\t\t\t</SendModeOption>\n\t\t))}\n\t</SendModeRow>\n);\n"],"names":["RADIO_ACTIVE_COLOR","COLORS","SendModeSelector","options","value","onChange","disabled","dataTest","SendModeRow","option","jsx","SendModeOption","RadioButton"],"mappings":"+OAKMA,EAAqBC,EAAAA,OAAO,WAAW,aAgChCC,EAAmB,CAA4B,CAC3D,QAAAC,EACA,MAAAC,EACA,SAAAC,EACA,SAAAC,EAAW,GACX,YAAaC,CACd,UACEC,cAAA,CAAY,YAAWD,EACtB,SAAAJ,EAAQ,IAAKM,GACbC,EAAAA,IAACC,EAAAA,eAAA,CAEA,OAAQP,IAAUK,EAAO,MACzB,SAAUH,GAAY,CAAC,CAACG,EAAO,SAC/B,YAAW,aAAaA,EAAO,KAAK,GACpC,QAAS,IAAM,CACVH,GAAYG,EAAO,UACvBJ,EAASI,EAAO,KAAK,CACtB,EAEA,SAAAC,EAAAA,IAACE,EAAAA,YAAA,CACA,SAAUR,IAAUK,EAAO,MAC3B,WAAYH,GAAY,CAAC,CAACG,EAAO,SACjC,MAAOA,EAAO,MACd,MAAOA,EAAO,MACd,cAAe,IAAM,CAChBH,GAAYG,EAAO,UACvBJ,EAASI,EAAO,KAAK,CACtB,EACA,WAAU,GACV,YAAaT,EACb,iBAAgB,EAAA,CAAA,CACjB,EArBKS,EAAO,KAsBb,CACA,CAAA,CACF"}