@12-apps/ui 6.87.0 → 6.88.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 (42) hide show
  1. package/components-catalog.md +1 -1
  2. package/dist/_internal/components/data-display/DayRuler/DayRuler.js +2 -2
  3. package/dist/_internal/components/data-display/ScheduleGrid/ScheduleGrid.js +6 -6
  4. package/dist/_internal/components/data-display/ScheduleGrid/ScheduleGrid.keyboard.js +2 -2
  5. package/dist/_internal/components/data-display/ScheduleGrid/ScheduleGrid.parts.js +3 -3
  6. package/dist/_internal/components/data-display/ScheduleGrid/ScheduleGrid.styles.js +1 -1
  7. package/dist/_internal/components/data-display/ScheduleGrid/schedule-grid-model.js +1 -1
  8. package/dist/_internal/components/data-display/ScheduleGrid/useGridDrag.js +2 -2
  9. package/dist/_internal/components/data-display/index.js +7 -7
  10. package/dist/_internal/components/index.js +7 -7
  11. package/dist/{chunk-I7CVC2DW.js → chunk-ARPOWDEO.js} +34 -14
  12. package/dist/chunk-ARPOWDEO.js.map +1 -0
  13. package/dist/{chunk-MQVYJVKV.js → chunk-E6UMTR2G.js} +2 -2
  14. package/dist/chunk-E6UMTR2G.js.map +1 -0
  15. package/dist/{chunk-D6JKCCRQ.js → chunk-MLIBJWQZ.js} +2 -2
  16. package/dist/{chunk-QQFFE3CQ.js → chunk-MPUOLKFT.js} +2 -2
  17. package/dist/{chunk-WCETCAZO.js → chunk-UIJU5X26.js} +5 -5
  18. package/dist/{chunk-B3SL5FP2.js → chunk-WBMLMLXP.js} +2 -2
  19. package/dist/{chunk-YSUJCKEE.js → chunk-WMTW4JXT.js} +7 -3
  20. package/dist/chunk-WMTW4JXT.js.map +1 -0
  21. package/dist/data-display/DayRuler.js +2 -2
  22. package/dist/data-display/ScheduleGrid.js +6 -6
  23. package/dist/types/components/data-display/ScheduleGrid/ScheduleGrid.parts.d.ts.map +1 -1
  24. package/dist/types/components/data-display/ScheduleGrid/ScheduleGrid.styles.d.ts +4 -1
  25. package/dist/types/components/data-display/ScheduleGrid/ScheduleGrid.styles.d.ts.map +1 -1
  26. package/dist/types/components/data-display/ScheduleGrid/ScheduleGrid.types.d.ts +23 -3
  27. package/dist/types/components/data-display/ScheduleGrid/ScheduleGrid.types.d.ts.map +1 -1
  28. package/dist/types/components/data-display/ScheduleGrid/schedule-grid-model.d.ts +1 -1
  29. package/dist/types/components/data-display/ScheduleGrid/schedule-grid-model.d.ts.map +1 -1
  30. package/package.json +1 -1
  31. package/src/components/data-display/ScheduleGrid/ScheduleGrid.md +35 -5
  32. package/src/components/data-display/ScheduleGrid/ScheduleGrid.parts.tsx +33 -8
  33. package/src/components/data-display/ScheduleGrid/ScheduleGrid.styles.ts +9 -2
  34. package/src/components/data-display/ScheduleGrid/ScheduleGrid.types.ts +23 -3
  35. package/src/components/data-display/ScheduleGrid/schedule-grid-model.ts +2 -2
  36. package/dist/chunk-I7CVC2DW.js.map +0 -1
  37. package/dist/chunk-MQVYJVKV.js.map +0 -1
  38. package/dist/chunk-YSUJCKEE.js.map +0 -1
  39. /package/dist/{chunk-D6JKCCRQ.js.map → chunk-MLIBJWQZ.js.map} +0 -0
  40. /package/dist/{chunk-QQFFE3CQ.js.map → chunk-MPUOLKFT.js.map} +0 -0
  41. /package/dist/{chunk-WCETCAZO.js.map → chunk-UIJU5X26.js.map} +0 -0
  42. /package/dist/{chunk-B3SL5FP2.js.map → chunk-WBMLMLXP.js.map} +0 -0
@@ -234,7 +234,7 @@ Components for displaying data, visualizations, and information to users.
234
234
  ### ScheduleGrid
235
235
  **Purpose**: A week grid of people (or resources) × days with blocks that have a start and an end
236
236
  **Use Cases**: Staff schedules (turnos), rosters, resource booking by day
237
- **Features**: Click an empty cell to create, drag across a row to create on each day, drag a block's edge grip to copy it along the row, drag its middle to move it, click to open; blocked (hatched) days refuse drops; a block's break drawn as a hatched gap; a name adornment and a chips slot per row; five tones that each carry their note text; sticky header row; keyboard twins (Shift+←/→ copy, Alt+←/→ move, arrows move focus) with a live region; touch never drags; read-only, loading, error, empty; container queries
237
+ **Features**: Click an empty cell to create, drag across a row to create on each day, drag a block's edge grip to copy it along the row, drag its middle to move it, click to open; blocked (hatched) days refuse drops; closed (gone) days offer no "+", refuse a create or a drop, draw no fill and carry a screen-reader-only label; past day headers in the secondary ink; a block's break drawn as a hatched gap; a name adornment and a chips slot per row; five tones that each carry their note text; sticky header row; keyboard twins (Shift+←/→ copy, Alt+←/→ move, arrows move focus) with a live region; touch never drags; read-only, loading, error, empty; container queries
238
238
  **Location**: `src/components/data-display/ScheduleGrid`
239
239
  **Docs**: `src/components/data-display/ScheduleGrid/ScheduleGrid.md`
240
240
 
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import {
3
3
  DayRuler
4
- } from "../../../../chunk-D6JKCCRQ.js";
4
+ } from "../../../../chunk-MLIBJWQZ.js";
5
5
  import "../../../../chunk-MAYAJXO6.js";
6
6
  import "../../../../chunk-IP424VZD.js";
7
7
  import "../../../../chunk-EEK2NK4W.js";
@@ -11,7 +11,7 @@ import "../../../../chunk-7ZQ3KQ7J.js";
11
11
  import "../../../../chunk-YMYJO2CZ.js";
12
12
  import "../../../../chunk-AC7K7IJE.js";
13
13
  import "../../../../chunk-6HZYRKOB.js";
14
- import "../../../../chunk-YSUJCKEE.js";
14
+ import "../../../../chunk-WMTW4JXT.js";
15
15
  import "../../../../chunk-3R6BR22L.js";
16
16
  import "../../../../chunk-YE44HUFF.js";
17
17
  import "../../../../chunk-35HMJQLO.js";
@@ -1,15 +1,15 @@
1
1
  "use client";
2
2
  import {
3
3
  ScheduleGrid
4
- } from "../../../../chunk-WCETCAZO.js";
5
- import "../../../../chunk-QQFFE3CQ.js";
6
- import "../../../../chunk-I7CVC2DW.js";
4
+ } from "../../../../chunk-UIJU5X26.js";
5
+ import "../../../../chunk-MPUOLKFT.js";
6
+ import "../../../../chunk-ARPOWDEO.js";
7
7
  import "../../../../chunk-GONPUJIE.js";
8
- import "../../../../chunk-B3SL5FP2.js";
9
- import "../../../../chunk-MQVYJVKV.js";
8
+ import "../../../../chunk-WBMLMLXP.js";
9
+ import "../../../../chunk-E6UMTR2G.js";
10
10
  import "../../../../chunk-AC7K7IJE.js";
11
11
  import "../../../../chunk-6HZYRKOB.js";
12
- import "../../../../chunk-YSUJCKEE.js";
12
+ import "../../../../chunk-WMTW4JXT.js";
13
13
  import "../../../../chunk-3R6BR22L.js";
14
14
  import "../../../../chunk-YE44HUFF.js";
15
15
  import "../../../../chunk-35HMJQLO.js";
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  focusables,
3
3
  handleGridKey
4
- } from "../../../../chunk-QQFFE3CQ.js";
5
- import "../../../../chunk-MQVYJVKV.js";
4
+ } from "../../../../chunk-MPUOLKFT.js";
5
+ import "../../../../chunk-E6UMTR2G.js";
6
6
  import "../../../../chunk-PZ5AY32C.js";
7
7
  export {
8
8
  focusables,
@@ -2,11 +2,11 @@ import {
2
2
  GridBody,
3
3
  GridCell,
4
4
  GridHeader
5
- } from "../../../../chunk-I7CVC2DW.js";
6
- import "../../../../chunk-MQVYJVKV.js";
5
+ } from "../../../../chunk-ARPOWDEO.js";
6
+ import "../../../../chunk-E6UMTR2G.js";
7
7
  import "../../../../chunk-AC7K7IJE.js";
8
8
  import "../../../../chunk-6HZYRKOB.js";
9
- import "../../../../chunk-YSUJCKEE.js";
9
+ import "../../../../chunk-WMTW4JXT.js";
10
10
  import "../../../../chunk-3R6BR22L.js";
11
11
  import "../../../../chunk-4HK4FVMV.js";
12
12
  import "../../../../chunk-TZ23DNKY.js";
@@ -21,7 +21,7 @@ import {
21
21
  skeletonCellSx,
22
22
  totalCellSx,
23
23
  totalHeaderSx
24
- } from "../../../../chunk-YSUJCKEE.js";
24
+ } from "../../../../chunk-WMTW4JXT.js";
25
25
  import "../../../../chunk-3R6BR22L.js";
26
26
  import "../../../../chunk-4HK4FVMV.js";
27
27
  import "../../../../chunk-TZ23DNKY.js";
@@ -5,7 +5,7 @@ import {
5
5
  daysBetween,
6
6
  isOpen,
7
7
  stepDay
8
- } from "../../../../chunk-MQVYJVKV.js";
8
+ } from "../../../../chunk-E6UMTR2G.js";
9
9
  import "../../../../chunk-PZ5AY32C.js";
10
10
  export {
11
11
  canDrop,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  useGridDrag
3
- } from "../../../../chunk-B3SL5FP2.js";
4
- import "../../../../chunk-MQVYJVKV.js";
3
+ } from "../../../../chunk-WBMLMLXP.js";
4
+ import "../../../../chunk-E6UMTR2G.js";
5
5
  import "../../../../chunk-YE44HUFF.js";
6
6
  import "../../../../chunk-PZ5AY32C.js";
7
7
  export {
@@ -134,12 +134,12 @@ import "../../../chunk-PUFA7FQ7.js";
134
134
  import "../../../chunk-7RXL4ONS.js";
135
135
  import {
136
136
  ScheduleGrid
137
- } from "../../../chunk-WCETCAZO.js";
138
- import "../../../chunk-QQFFE3CQ.js";
139
- import "../../../chunk-I7CVC2DW.js";
137
+ } from "../../../chunk-UIJU5X26.js";
138
+ import "../../../chunk-MPUOLKFT.js";
139
+ import "../../../chunk-ARPOWDEO.js";
140
140
  import "../../../chunk-GONPUJIE.js";
141
- import "../../../chunk-B3SL5FP2.js";
142
- import "../../../chunk-MQVYJVKV.js";
141
+ import "../../../chunk-WBMLMLXP.js";
142
+ import "../../../chunk-E6UMTR2G.js";
143
143
  import {
144
144
  SectionOnboarding
145
145
  } from "../../../chunk-AD6GRJFV.js";
@@ -208,7 +208,7 @@ import "../../../chunk-G3E66C6J.js";
208
208
  import "../../../chunk-TTRWOI6Z.js";
209
209
  import {
210
210
  DayRuler
211
- } from "../../../chunk-D6JKCCRQ.js";
211
+ } from "../../../chunk-MLIBJWQZ.js";
212
212
  import "../../../chunk-MAYAJXO6.js";
213
213
  import "../../../chunk-IP424VZD.js";
214
214
  import "../../../chunk-EEK2NK4W.js";
@@ -218,7 +218,7 @@ import "../../../chunk-7ZQ3KQ7J.js";
218
218
  import "../../../chunk-YMYJO2CZ.js";
219
219
  import "../../../chunk-AC7K7IJE.js";
220
220
  import "../../../chunk-6HZYRKOB.js";
221
- import "../../../chunk-YSUJCKEE.js";
221
+ import "../../../chunk-WMTW4JXT.js";
222
222
  import "../../../chunk-3R6BR22L.js";
223
223
  import "../../../chunk-YE44HUFF.js";
224
224
  import "../../../chunk-35HMJQLO.js";
@@ -590,12 +590,12 @@ import "../../chunk-PUFA7FQ7.js";
590
590
  import "../../chunk-7RXL4ONS.js";
591
591
  import {
592
592
  ScheduleGrid
593
- } from "../../chunk-WCETCAZO.js";
594
- import "../../chunk-QQFFE3CQ.js";
595
- import "../../chunk-I7CVC2DW.js";
593
+ } from "../../chunk-UIJU5X26.js";
594
+ import "../../chunk-MPUOLKFT.js";
595
+ import "../../chunk-ARPOWDEO.js";
596
596
  import "../../chunk-GONPUJIE.js";
597
- import "../../chunk-B3SL5FP2.js";
598
- import "../../chunk-MQVYJVKV.js";
597
+ import "../../chunk-WBMLMLXP.js";
598
+ import "../../chunk-E6UMTR2G.js";
599
599
  import {
600
600
  SectionOnboarding
601
601
  } from "../../chunk-AD6GRJFV.js";
@@ -797,7 +797,7 @@ import "../../chunk-G3E66C6J.js";
797
797
  import "../../chunk-TTRWOI6Z.js";
798
798
  import {
799
799
  DayRuler
800
- } from "../../chunk-D6JKCCRQ.js";
800
+ } from "../../chunk-MLIBJWQZ.js";
801
801
  import "../../chunk-MAYAJXO6.js";
802
802
  import "../../chunk-IP424VZD.js";
803
803
  import "../../chunk-EEK2NK4W.js";
@@ -807,7 +807,7 @@ import "../../chunk-7ZQ3KQ7J.js";
807
807
  import "../../chunk-YMYJO2CZ.js";
808
808
  import "../../chunk-AC7K7IJE.js";
809
809
  import "../../chunk-6HZYRKOB.js";
810
- import "../../chunk-YSUJCKEE.js";
810
+ import "../../chunk-WMTW4JXT.js";
811
811
  import "../../chunk-3R6BR22L.js";
812
812
  import "../../chunk-YE44HUFF.js";
813
813
  import "../../chunk-35HMJQLO.js";
@@ -1,11 +1,12 @@
1
1
  import {
2
2
  daysBetween,
3
3
  isOpen
4
- } from "./chunk-MQVYJVKV.js";
4
+ } from "./chunk-E6UMTR2G.js";
5
5
  import {
6
6
  ScheduleNameCell
7
7
  } from "./chunk-AC7K7IJE.js";
8
8
  import {
9
+ SR_ONLY_SX,
9
10
  blockSx,
10
11
  blockedLabelSx,
11
12
  breakSx,
@@ -22,7 +23,7 @@ import {
22
23
  skeletonCellSx,
23
24
  totalCellSx,
24
25
  totalHeaderSx
25
- } from "./chunk-YSUJCKEE.js";
26
+ } from "./chunk-WMTW4JXT.js";
26
27
  import {
27
28
  SCHEDULE_GRID_METRICS
28
29
  } from "./chunk-3R6BR22L.js";
@@ -117,17 +118,26 @@ function CellFill({ props, ghost }) {
117
118
  if (!cell.blocked || cell.blocks.length > 0 || !cell.blockedLabel) return null;
118
119
  return /* @__PURE__ */ jsx(Box, { component: "span", sx: blockedLabelSx, "aria-hidden": true, title: cell.blockedLabel, children: cell.blockedLabel });
119
120
  }
120
- function GridCell(props) {
121
- const { row, day, column, cell, drag, can, labels, testId } = props;
122
- const ghost = ghostFor(props);
123
- const blocked = Boolean(cell.blocked);
124
- const look = {
121
+ function ClosedWords({ cell }) {
122
+ if (!cell.closed || cell.blocked || !cell.closedLabel) return null;
123
+ return /* @__PURE__ */ jsx(Box, { component: "span", sx: SR_ONLY_SX, children: cell.closedLabel });
124
+ }
125
+ function lookOf(props, ghost) {
126
+ const { row, day, column, cell, drag, can } = props;
127
+ return {
125
128
  today: Boolean(column.today),
126
- blocked,
129
+ blocked: Boolean(cell.blocked),
130
+ closed: Boolean(cell.closed),
127
131
  target: ghost !== null,
128
132
  over: drag?.mode === "move" && drag.moved && drag.rowId === row.id && drag.day === day,
129
133
  interactive: can.create && isOpen(cell)
130
134
  };
135
+ }
136
+ function GridCell(props) {
137
+ const { row, day, column, cell, can, labels, testId } = props;
138
+ const ghost = ghostFor(props);
139
+ const look = lookOf(props, ghost);
140
+ const blocked = look.blocked;
131
141
  const closedName = blocked && cell.blocks.length === 0 ? cell.blockedLabel ?? labels.blockedCell(row.label, column.label) : void 0;
132
142
  return /* @__PURE__ */ jsxs(
133
143
  Box,
@@ -153,7 +163,8 @@ function GridCell(props) {
153
163
  },
154
164
  block.id
155
165
  )),
156
- /* @__PURE__ */ jsx(CellFill, { props, ghost })
166
+ /* @__PURE__ */ jsx(CellFill, { props, ghost }),
167
+ /* @__PURE__ */ jsx(ClosedWords, { cell })
157
168
  ]
158
169
  }
159
170
  );
@@ -168,10 +179,19 @@ function keepDatesWhole(label) {
168
179
  function GridHeader({ columns, totalLabel, rowSx, testId }) {
169
180
  return /* @__PURE__ */ jsxs(Box, { role: "row", sx: [rowSx, headerRowSx], "data-testid": `${testId}-header`, children: [
170
181
  /* @__PURE__ */ jsx("span", { role: "cell", "data-sg-corner": "" }),
171
- columns.map((column, day) => /* @__PURE__ */ jsxs(Box, { role: "columnheader", sx: headerCellSx(Boolean(column.today)), children: [
172
- /* @__PURE__ */ jsx("span", { "data-sg-col": "full", title: column.label, children: keepDatesWhole(column.label) }),
173
- column.sublabel ? /* @__PURE__ */ jsx(Box, { component: "span", sx: headerSublabelSx, "data-sg-col": "sub", children: column.sublabel }) : null
174
- ] }, `${day}-${column.label}`)),
182
+ columns.map((column, day) => /* @__PURE__ */ jsxs(
183
+ Box,
184
+ {
185
+ role: "columnheader",
186
+ sx: headerCellSx(Boolean(column.today), Boolean(column.past)),
187
+ "data-sg-past": column.past ? "" : void 0,
188
+ children: [
189
+ /* @__PURE__ */ jsx("span", { "data-sg-col": "full", title: column.label, children: keepDatesWhole(column.label) }),
190
+ column.sublabel ? /* @__PURE__ */ jsx(Box, { component: "span", sx: headerSublabelSx, "data-sg-col": "sub", children: column.sublabel }) : null
191
+ ]
192
+ },
193
+ `${day}-${column.label}`
194
+ )),
175
195
  totalLabel !== void 0 ? /* @__PURE__ */ jsx(Box, { role: "columnheader", sx: totalHeaderSx, children: totalLabel }) : null
176
196
  ] });
177
197
  }
@@ -226,4 +246,4 @@ export {
226
246
  GridHeader,
227
247
  GridBody
228
248
  };
229
- //# sourceMappingURL=chunk-I7CVC2DW.js.map
249
+ //# sourceMappingURL=chunk-ARPOWDEO.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/data-display/ScheduleGrid/ScheduleGrid.parts.tsx"],"sourcesContent":["import AddIcon from '@mui/icons-material/Add';\nimport Box from '@mui/material/Box/index.js';\nimport type { CSSObject, Theme } from '@mui/material/styles/index.js';\nimport type * as React from 'react';\n\nimport type { ScheduleGridLabels } from '../../../copy/labels';\nimport { daysBetween, isOpen } from './schedule-grid-model';\nimport { SCHEDULE_GRID_METRICS } from './ScheduleGrid.metrics';\nimport {\n blockedLabelSx,\n blockSx,\n breakSx,\n cellSx,\n ghostSx,\n gripSx,\n groupTitleSx,\n headerCellSx,\n headerSublabelSx,\n headerRowSx,\n nameCellSx,\n personRowSx,\n plusButtonSx,\n skeletonCellSx,\n SR_ONLY_SX,\n totalCellSx,\n totalHeaderSx,\n} from './ScheduleGrid.styles';\nimport type { CellLook } from './ScheduleGrid.styles';\nimport type {\n ScheduleGridBlock,\n ScheduleGridCell,\n ScheduleGridColumn,\n ScheduleGridProps,\n ScheduleGridRow,\n} from './ScheduleGrid.types';\nimport { ScheduleNameCell } from './ScheduleNameCell';\nimport type { GridDrag, GridDragApi } from './useGridDrag';\n\n/** What the grid lets a cell do, resolved once per render. */\nexport interface CellAbilities {\n create: boolean;\n copy: boolean;\n move: boolean;\n}\n\n/** A row's shared columns, as an `sx` part. */\ntype RowSx = (theme: Theme) => CSSObject;\n\ninterface CellProps {\n row: ScheduleGridRow;\n day: number;\n column: ScheduleGridColumn;\n cell: ScheduleGridCell;\n drag: GridDrag | null;\n dragApi: GridDragApi;\n can: CellAbilities;\n createPreview?: (rowId: string) => string;\n onCreate?: (rowId: string, days: number[]) => void;\n onBlockClick?: (blockId: string) => void;\n labels: ScheduleGridLabels;\n testId: string;\n}\n\n/** The ghost text this cell shows during a create or copy, or `null` when the gesture does not land here. */\nfunction ghostFor(props: CellProps): string | null {\n const { drag, row, day, cell, createPreview } = props;\n if (!drag || drag.mode === 'move' || drag.rowId !== row.id || !isOpen(cell)) return null;\n if (!daysBetween(drag.anchor, drag.day).includes(day)) return null;\n if (drag.mode === 'copy') return day === drag.anchor ? null : drag.preview;\n return createPreview?.(row.id) ?? '';\n}\n\n/** The keys a block answers to, for `aria-keyshortcuts`. */\nfunction shortcutsOf(movable: boolean, copyable: boolean): string | undefined {\n const keys = [movable ? 'Alt+ArrowLeft Alt+ArrowRight' : '', copyable ? 'Shift+ArrowLeft Shift+ArrowRight' : ''];\n return keys.filter(Boolean).join(' ') || undefined;\n}\n\nconst titleOf = (block: ScheduleGridBlock): string => block.title ?? [block.label, block.note].filter(Boolean).join(' · ');\n\ninterface BlockProps {\n block: ScheduleGridBlock;\n row: ScheduleGridRow;\n day: number;\n can: CellAbilities;\n dragApi: GridDragApi;\n onBlockClick?: (blockId: string) => void;\n testId: string;\n}\n\nfunction Grip({ side, onPointerDown, testId }: { side: 'l' | 'r'; onPointerDown: (event: React.PointerEvent) => void; testId: string }) {\n return <Box component=\"span\" aria-hidden sx={gripSx(side)} onPointerDown={onPointerDown} data-sg-grip=\"\" data-testid={testId} />;\n}\n\n/** The block's break, kept inside it whatever the host sent. */\nfunction BreakBand({ span, testId }: { span: { start: number; end: number }; testId: string }): React.JSX.Element | null {\n const start = Math.min(1, Math.max(0, span.start));\n const end = Math.min(1, Math.max(0, span.end));\n if (!(end > start)) return null;\n return <Box component=\"span\" aria-hidden sx={breakSx({ start, end })} data-sg-break=\"\" data-testid={testId} />;\n}\n\nfunction BlockButton({ block, row, day, can, dragApi, onBlockClick, testId }: BlockProps): React.JSX.Element {\n const movable = can.move && Boolean(block.movable);\n const copyable = can.copy && Boolean(block.copyable);\n const startCopy = (event: React.PointerEvent): void => dragApi.startCopy(event, block.id, row.id, day, block.label);\n const startMove = (event: React.PointerEvent): void => dragApi.startMove(event, block.id, row.id, day);\n return (\n <Box\n component=\"button\"\n type=\"button\"\n sx={blockSx(block.tone, { selected: Boolean(block.selected), movable })}\n title={titleOf(block)}\n aria-keyshortcuts={shortcutsOf(movable, copyable)}\n aria-current={block.selected ? 'true' : undefined}\n data-sg-focus=\"\"\n data-sg-row={row.id}\n data-sg-day={day}\n data-sg-block={block.id}\n data-tone={block.tone}\n data-testid={`${testId}-block-${block.id}`}\n onPointerDown={movable ? startMove : undefined}\n onClick={() => {\n if (!dragApi.takeClick()) onBlockClick?.(block.id);\n }}\n >\n {block.breakSpan ? <BreakBand span={block.breakSpan} testId={`${testId}-break-${block.id}`} /> : null}\n {copyable ? <Grip side=\"l\" onPointerDown={startCopy} testId={`${testId}-grip-l-${block.id}`} /> : null}\n <span data-sg-line=\"label\">{block.label}</span>\n {block.note ? <span data-sg-line=\"note\">{block.note}</span> : null}\n {copyable ? <Grip side=\"r\" onPointerDown={startCopy} testId={`${testId}-grip-r-${block.id}`} /> : null}\n </Box>\n );\n}\n\n/**\n * The empty cell's \"+\". It stays mounted while a drag shows the ghost in it, so\n * a press and release in place is still its click.\n */\nfunction PlusButton({ props, ghost }: { props: CellProps; ghost: string | null }): React.JSX.Element {\n const { row, day, column, dragApi, onCreate, labels } = props;\n return (\n <Box\n component=\"button\"\n type=\"button\"\n sx={plusButtonSx}\n aria-label={labels.createCell(row.label, column.label)}\n data-ghost={ghost === null ? undefined : ''}\n data-sg-focus=\"\"\n data-sg-row={row.id}\n data-sg-day={day}\n onPointerDown={(event: React.PointerEvent) => dragApi.startCreate(event, row.id, day)}\n onClick={() => {\n if (!dragApi.takeClick()) onCreate?.(row.id, [day]);\n }}\n >\n {ghost === null ? <AddIcon aria-hidden /> : <Ghost text={ghost} />}\n </Box>\n );\n}\n\nfunction Ghost({ text }: { text: string }): React.JSX.Element {\n return (\n <Box component=\"span\" sx={ghostSx} aria-hidden>\n {text}\n </Box>\n );\n}\n\n/** What fills a cell after its blocks: the \"+\" (or the ghost in it), a lone ghost, or a closed day's label. */\nfunction CellFill({ props, ghost }: { props: CellProps; ghost: string | null }): React.JSX.Element | null {\n const { cell, can } = props;\n if (can.create && isOpen(cell)) return <PlusButton props={props} ghost={ghost} />;\n if (ghost !== null) return <Ghost text={ghost} />;\n if (!cell.blocked || cell.blocks.length > 0 || !cell.blockedLabel) return null;\n return (\n <Box component=\"span\" sx={blockedLabelSx} aria-hidden title={cell.blockedLabel}>\n {cell.blockedLabel}\n </Box>\n );\n}\n\n/** A gone day's words for a screen reader (\"Já passou\"): visually hidden, and only when the host gives them. */\nfunction ClosedWords({ cell }: { cell: ScheduleGridCell }): React.JSX.Element | null {\n if (!cell.closed || cell.blocked || !cell.closedLabel) return null;\n return (\n <Box component=\"span\" sx={SR_ONLY_SX}>\n {cell.closedLabel}\n </Box>\n );\n}\n\n/** How the cell is drawn right now. */\nfunction lookOf(props: CellProps, ghost: string | null): CellLook {\n const { row, day, column, cell, drag, can } = props;\n return {\n today: Boolean(column.today),\n blocked: Boolean(cell.blocked),\n closed: Boolean(cell.closed),\n target: ghost !== null,\n over: drag?.mode === 'move' && drag.moved && drag.rowId === row.id && drag.day === day,\n interactive: can.create && isOpen(cell),\n };\n}\n\n/** One day of one row: its blocks, a \"+\" when it is empty, the hatch when it is closed. */\nexport function GridCell(props: CellProps): React.JSX.Element {\n const { row, day, column, cell, can, labels, testId } = props;\n const ghost = ghostFor(props);\n const look = lookOf(props, ghost);\n const blocked = look.blocked;\n const closedName = blocked && cell.blocks.length === 0 ? (cell.blockedLabel ?? labels.blockedCell(row.label, column.label)) : undefined;\n return (\n <Box\n role=\"cell\"\n sx={cellSx(look)}\n data-sg-cell=\"\"\n data-sg-row={row.id}\n data-sg-day={day}\n data-testid={`${testId}-cell-${row.id}-${day}`}\n aria-label={closedName}\n >\n {cell.blocks.map((block) => (\n <BlockButton\n key={block.id}\n block={block}\n row={row}\n day={day}\n can={can}\n dragApi={props.dragApi}\n onBlockClick={props.onBlockClick}\n testId={testId}\n />\n ))}\n <CellFill props={props} ghost={ghost} />\n <ClosedWords cell={cell} />\n </Box>\n );\n}\n\n/** The first column: the person, as both views draw it. */\nfunction NameCell({ row }: { row: ScheduleGridRow }): React.JSX.Element {\n const sizes = { name: SCHEDULE_GRID_METRICS.rowName, meta: SCHEDULE_GRID_METRICS.rowMeta, chipsTop: 0.5 };\n return <ScheduleNameCell row={row} role=\"rowheader\" sx={nameCellSx} sizes={sizes} />;\n}\n\ninterface HeaderProps {\n columns: readonly ScheduleGridColumn[];\n /** Present when the grid has a last column. */\n totalLabel?: string;\n rowSx: RowSx;\n testId: string;\n}\n\n/** The days, their counts and the total column's header — pinned while the grid scrolls. */\n\n/** A label wraps between words, never inside \"Seg 19/10\": the space before a number holds. */\nfunction keepDatesWhole(label: string): string {\n return label.replace(/ (?=\\d)/g, '\\u00a0');\n}\n\nexport function GridHeader({ columns, totalLabel, rowSx, testId }: HeaderProps): React.JSX.Element {\n return (\n <Box role=\"row\" sx={[rowSx, headerRowSx]} data-testid={`${testId}-header`}>\n {/* Above the names: a cell of the header row, with nothing to head. */}\n <span role=\"cell\" data-sg-corner=\"\" />\n {columns.map((column, day) => (\n <Box\n role=\"columnheader\"\n key={`${day}-${column.label}`}\n sx={headerCellSx(Boolean(column.today), Boolean(column.past))}\n data-sg-past={column.past ? '' : undefined}\n >\n <span data-sg-col=\"full\" title={column.label}>\n {keepDatesWhole(column.label)}\n </span>\n {column.sublabel ? (\n <Box component=\"span\" sx={headerSublabelSx} data-sg-col=\"sub\">\n {column.sublabel}\n </Box>\n ) : null}\n </Box>\n ))}\n {totalLabel !== undefined ? (\n <Box role=\"columnheader\" sx={totalHeaderSx}>\n {totalLabel}\n </Box>\n ) : null}\n </Box>\n );\n}\n\ninterface BodyProps {\n grid: ScheduleGridProps;\n rows: readonly ScheduleGridRow[];\n rowSx: RowSx;\n hasTotal: boolean;\n can: CellAbilities;\n dragApi: GridDragApi;\n labels: ScheduleGridLabels;\n testId: string;\n}\n\nfunction SkeletonRows({ grid, rowSx, testId }: Pick<BodyProps, 'grid' | 'rowSx' | 'testId'>): React.JSX.Element {\n return (\n <>\n {Array.from({ length: SCHEDULE_GRID_METRICS.skeletonRows }, (_, index) => (\n <Box key={index} sx={[rowSx, personRowSx]} aria-hidden data-testid={`${testId}-loading`}>\n <Box sx={skeletonCellSx} />\n {grid.columns.map((column, day) => (\n <Box key={`${day}-${column.label}`} sx={skeletonCellSx} />\n ))}\n </Box>\n ))}\n </>\n );\n}\n\nfunction PersonRow({ row, body }: { row: ScheduleGridRow; body: BodyProps }): React.JSX.Element {\n const { grid, rowSx, hasTotal, can, dragApi, labels, testId } = body;\n return (\n <Box role=\"row\" sx={[rowSx, personRowSx]} data-testid={`${testId}-row-${row.id}`}>\n <NameCell row={row} />\n {grid.columns.map((column, day) => (\n <GridCell\n key={`${day}-${column.label}`}\n row={row}\n day={day}\n column={column}\n cell={grid.cell(row.id, day)}\n drag={dragApi.drag}\n dragApi={dragApi}\n can={can}\n createPreview={grid.createPreview}\n onCreate={grid.onCreate}\n onBlockClick={grid.onBlockClick}\n labels={labels}\n testId={testId}\n />\n ))}\n {hasTotal ? (\n <Box role=\"cell\" sx={totalCellSx}>\n {row.total}\n </Box>\n ) : null}\n </Box>\n );\n}\n\n/** The host's error or empty node, as the table's one full-width row (a table holds rows only). */\nfunction MessageRow({ children, testId }: { children: React.ReactNode; testId: string }): React.JSX.Element | null {\n if (children === null || children === undefined || children === false) return null;\n return (\n <Box role=\"row\" data-testid={`${testId}-message`}>\n <Box role=\"cell\">{children}</Box>\n </Box>\n );\n}\n\n/** The groups and their rows — or the skeleton, the host's error, or the host's empty state. */\nexport function GridBody(body: BodyProps): React.JSX.Element | null {\n const { grid, rows } = body;\n if (grid.error) return <MessageRow testId={body.testId}>{grid.error}</MessageRow>;\n if (grid.loading) return <SkeletonRows grid={grid} rowSx={body.rowSx} testId={body.testId} />;\n if (rows.length === 0) return <MessageRow testId={body.testId}>{grid.empty}</MessageRow>;\n return (\n <>\n {grid.groups.map((group, index) => (\n <Box role=\"rowgroup\" key={`${index}-${group.title ?? ''}`} aria-label={group.title}>\n {group.title ? (\n <Box component=\"p\" sx={groupTitleSx} aria-hidden data-sg-group-title=\"\">\n {group.title}\n </Box>\n ) : null}\n {group.rows.map((row) => (\n <PersonRow key={row.id} row={row} body={body} />\n ))}\n </Box>\n ))}\n </>\n );\n}\n"],"mappings":"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","names":[]}
@@ -1,6 +1,6 @@
1
1
  // src/components/data-display/ScheduleGrid/schedule-grid-model.ts
2
2
  function isOpen(cell) {
3
- return !cell.blocked && cell.blocks.length === 0;
3
+ return !cell.blocked && !cell.closed && cell.blocks.length === 0;
4
4
  }
5
5
  function daysBetween(a, b) {
6
6
  const from = Math.min(a, b);
@@ -29,4 +29,4 @@ export {
29
29
  canDrop,
30
30
  stepDay
31
31
  };
32
- //# sourceMappingURL=chunk-MQVYJVKV.js.map
32
+ //# sourceMappingURL=chunk-E6UMTR2G.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/data-display/ScheduleGrid/schedule-grid-model.ts"],"sourcesContent":["import type { ScheduleGridCell } from './ScheduleGrid.types';\n\n/**\n * THE GRID'S RULES, as pure functions (FUT-3825): which days a gesture lands\n * on. The host decides everything else — hours, limits, refusals.\n */\n\n/** A cell that can take a new turno: nothing in it, not closed to the row (`blocked`) and not gone (`closed`). */\nexport function isOpen(cell: ScheduleGridCell): boolean {\n return !cell.blocked && !cell.closed && cell.blocks.length === 0;\n}\n\n/** Every day from `a` to `b` inclusive, in order, whichever is larger. */\nexport function daysBetween(a: number, b: number): number[] {\n const from = Math.min(a, b);\n const to = Math.max(a, b);\n return Array.from({ length: to - from + 1 }, (_, index) => from + index);\n}\n\n/** A create across `anchor…current` of one row: the crossed days that are open (G-R1). */\nexport function createTargets(cellOf: (day: number) => ScheduleGridCell, anchor: number, current: number): number[] {\n return daysBetween(anchor, current).filter((day) => isOpen(cellOf(day)));\n}\n\n/** A copy of the block on `source` across `source…current`: never its own day, never a taken or closed one (G-R2). */\nexport function copyTargets(cellOf: (day: number) => ScheduleGridCell, source: number, current: number): number[] {\n return daysBetween(source, current).filter((day) => day !== source && isOpen(cellOf(day)));\n}\n\n/** A move may land on an open cell that is not its own (G-R3). */\nexport function canDrop(target: ScheduleGridCell, sameCell: boolean): boolean {\n return !sameCell && isOpen(target);\n}\n\n/** The day one step left (-1) or right (+1) of `day`, or `undefined` past either end. */\nexport function stepDay(day: number, direction: -1 | 1, dayCount: number): number | undefined {\n const next = day + direction;\n return next >= 0 && next < dayCount ? next : undefined;\n}\n"],"mappings":";AAQO,SAAS,OAAO,MAAiC;AACtD,SAAO,CAAC,KAAK,WAAW,CAAC,KAAK,UAAU,KAAK,OAAO,WAAW;AACjE;AAGO,SAAS,YAAY,GAAW,GAAqB;AAC1D,QAAM,OAAO,KAAK,IAAI,GAAG,CAAC;AAC1B,QAAM,KAAK,KAAK,IAAI,GAAG,CAAC;AACxB,SAAO,MAAM,KAAK,EAAE,QAAQ,KAAK,OAAO,EAAE,GAAG,CAAC,GAAG,UAAU,OAAO,KAAK;AACzE;AAGO,SAAS,cAAc,QAA2C,QAAgB,SAA2B;AAClH,SAAO,YAAY,QAAQ,OAAO,EAAE,OAAO,CAAC,QAAQ,OAAO,OAAO,GAAG,CAAC,CAAC;AACzE;AAGO,SAAS,YAAY,QAA2C,QAAgB,SAA2B;AAChH,SAAO,YAAY,QAAQ,OAAO,EAAE,OAAO,CAAC,QAAQ,QAAQ,UAAU,OAAO,OAAO,GAAG,CAAC,CAAC;AAC3F;AAGO,SAAS,QAAQ,QAA0B,UAA4B;AAC5E,SAAO,CAAC,YAAY,OAAO,MAAM;AACnC;AAGO,SAAS,QAAQ,KAAa,WAAmB,UAAsC;AAC5F,QAAM,OAAO,MAAM;AACnB,SAAO,QAAQ,KAAK,OAAO,WAAW,OAAO;AAC/C;","names":[]}
@@ -22,7 +22,7 @@ import {
22
22
  } from "./chunk-7ZQ3KQ7J.js";
23
23
  import {
24
24
  SR_ONLY_SX
25
- } from "./chunk-YSUJCKEE.js";
25
+ } from "./chunk-WMTW4JXT.js";
26
26
  import {
27
27
  useAnnouncer
28
28
  } from "./chunk-35HMJQLO.js";
@@ -117,4 +117,4 @@ function DayRuler(props) {
117
117
  export {
118
118
  DayRuler
119
119
  };
120
- //# sourceMappingURL=chunk-D6JKCCRQ.js.map
120
+ //# sourceMappingURL=chunk-MLIBJWQZ.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  isOpen,
3
3
  stepDay
4
- } from "./chunk-MQVYJVKV.js";
4
+ } from "./chunk-E6UMTR2G.js";
5
5
 
6
6
  // src/components/data-display/ScheduleGrid/ScheduleGrid.keyboard.ts
7
7
  function focusables(root) {
@@ -87,4 +87,4 @@ export {
87
87
  focusables,
88
88
  handleGridKey
89
89
  };
90
- //# sourceMappingURL=chunk-QQFFE3CQ.js.map
90
+ //# sourceMappingURL=chunk-MPUOLKFT.js.map
@@ -1,17 +1,17 @@
1
1
  import {
2
2
  focusables,
3
3
  handleGridKey
4
- } from "./chunk-QQFFE3CQ.js";
4
+ } from "./chunk-MPUOLKFT.js";
5
5
  import {
6
6
  GridBody,
7
7
  GridHeader
8
- } from "./chunk-I7CVC2DW.js";
8
+ } from "./chunk-ARPOWDEO.js";
9
9
  import {
10
10
  useSidewaysScroll
11
11
  } from "./chunk-GONPUJIE.js";
12
12
  import {
13
13
  useGridDrag
14
- } from "./chunk-B3SL5FP2.js";
14
+ } from "./chunk-WBMLMLXP.js";
15
15
  import {
16
16
  SR_ONLY_SX,
17
17
  frameSx,
@@ -19,7 +19,7 @@ import {
19
19
  rootSx,
20
20
  rowGridSx,
21
21
  scrollSx
22
- } from "./chunk-YSUJCKEE.js";
22
+ } from "./chunk-WMTW4JXT.js";
23
23
  import {
24
24
  useAnnouncer
25
25
  } from "./chunk-35HMJQLO.js";
@@ -137,4 +137,4 @@ function ScheduleGrid(props) {
137
137
  export {
138
138
  ScheduleGrid
139
139
  };
140
- //# sourceMappingURL=chunk-WCETCAZO.js.map
140
+ //# sourceMappingURL=chunk-UIJU5X26.js.map
@@ -2,7 +2,7 @@ import {
2
2
  canDrop,
3
3
  copyTargets,
4
4
  createTargets
5
- } from "./chunk-MQVYJVKV.js";
5
+ } from "./chunk-E6UMTR2G.js";
6
6
  import {
7
7
  useDragWindow,
8
8
  useTrailingClick
@@ -91,4 +91,4 @@ function useGridDrag(rootRef, handlers) {
91
91
  export {
92
92
  useGridDrag
93
93
  };
94
- //# sourceMappingURL=chunk-B3SL5FP2.js.map
94
+ //# sourceMappingURL=chunk-WBMLMLXP.js.map
@@ -105,11 +105,14 @@ var headerRowSx = (theme) => ({
105
105
  paddingTop: theme.spacing(0.75),
106
106
  paddingBottom: theme.spacing(0.75)
107
107
  });
108
- function headerCellSx(today) {
108
+ function headerCellSx(today, past = false) {
109
+ let color = "text.primary";
110
+ if (past) color = "text.secondary";
111
+ if (today) color = "primary.main";
109
112
  return {
110
113
  fontSize: sxRem(SCHEDULE_GRID_METRICS.headerLabel),
111
114
  fontWeight: 500,
112
- color: today ? "primary.main" : "text.primary",
115
+ color,
113
116
  p: 0.5,
114
117
  minWidth: 0,
115
118
  // A long label ("Hoje · Seg 19/10") wraps to a second line, as the prototype's: never cut.
@@ -180,6 +183,7 @@ function cellSx(look) {
180
183
  if (look.blocked) {
181
184
  return { ...base, background: hatch(theme), borderColor: theme.palette.divider, cursor: "not-allowed" };
182
185
  }
186
+ if (look.closed) return { ...base, backgroundColor: "transparent", borderColor: theme.palette.divider };
183
187
  if (look.target) {
184
188
  return {
185
189
  ...base,
@@ -338,4 +342,4 @@ export {
338
342
  skeletonCellSx,
339
343
  SR_ONLY_SX
340
344
  };
341
- //# sourceMappingURL=chunk-YSUJCKEE.js.map
345
+ //# sourceMappingURL=chunk-WMTW4JXT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/data-display/ScheduleGrid/ScheduleGrid.styles.ts"],"sourcesContent":["import type { SxProps, Theme } from '@mui/material/styles/index.js';\nimport type { CSSObject } from '@mui/material/styles/index.js';\n\nimport { rem, sxRem } from '../../../tokens/relative';\nimport { SCHEDULE_GRID_METRICS as M } from './ScheduleGrid.metrics';\nimport { blockToneStyles, breakHatch } from './schedule-tones';\nimport type { ScheduleBlockTone } from './ScheduleGrid.types';\n\n/**\n * The grid's root: the container the column widths answer to (container\n * queries, never media queries — the grid may sit in a narrow pane).\n */\nexport const rootSx: SxProps<Theme> = { containerType: 'inline-size', minWidth: 0, width: '100%' };\n\n/** The columns a row has: the name, the days, the total (when there is one). */\nfunction trackCount(dayCount: number, hasTotal: boolean): number {\n return 1 + dayCount + (hasTotal ? 1 : 0);\n}\n\n/**\n * The narrowest container a layout fits in, in px: its name column, its days\n * at their minimum, its total, and the gaps between them — for THIS grid's\n * day count, so a fortnight scrolls where a week still fits.\n */\nfunction fitsFrom(dayCount: number, hasTotal: boolean, name: number, day: number, total: number): number {\n return name + dayCount * day + (hasTotal ? total : 0) + (trackCount(dayCount, hasTotal) - 1) * M.gap;\n}\n\n/** `@container (width < px)`: every bound is \"from px up\" (ranges are exclusive below, inclusive above). */\nfunction below(theme: Theme, px: number): string {\n return `@container (width < ${rem(theme, px)})`;\n}\n\n/**\n * The column widths, as variables every row reads, by the container's width:\n * - from `wide` up: 200px names, days of at least 104px with their grips;\n * - from `compact` up: 140px names, 40px total, days of at least 98px — still\n * unscrolled, grips kept, the header row sticking to the page;\n * - below `compact`: days of at least 152px, grips kept; the body scrolls\n * sideways under the pinned names and the header row follows it sideways\n * while it still sticks to the page (`useSidewaysScroll` sets its scroll);\n * - below 600px: 120px names, 136px days, no grips.\n * The `wide` and `compact` bounds come from this grid's own day count\n * (`fitsFrom`). Container queries, never media queries.\n */\nexport function frameSx(dayCount: number, hasTotal: boolean): SxProps<Theme> {\n return (theme: Theme) => {\n const terms = ['var(--sg-name)', `${dayCount} * var(--sg-day)`, `${trackCount(dayCount, hasTotal) - 1} * ${rem(theme, M.gap)}`];\n if (hasTotal) terms.push('var(--sg-total)');\n const wide = fitsFrom(dayCount, hasTotal, M.nameColumn.wide, M.dayMin.wide, M.totalColumn.wide);\n const compact = fitsFrom(dayCount, hasTotal, M.nameColumn.compact, M.dayMin.compact, M.totalColumn.compact);\n return {\n '--sg-name': rem(theme, M.nameColumn.wide),\n '--sg-total': rem(theme, M.totalColumn.wide),\n '--sg-day': rem(theme, M.dayMin.wide),\n // What every row is at least: its own columns at their minimums.\n '--sg-min': `calc(${terms.join(' + ')})`,\n [below(theme, wide)]: {\n '--sg-name': rem(theme, M.nameColumn.compact),\n '--sg-total': rem(theme, M.totalColumn.compact),\n '--sg-day': rem(theme, M.dayMin.compact),\n '& [data-sg-block]': { paddingLeft: rem(theme, M.blockPadding.tight), paddingRight: rem(theme, M.blockPadding.tight) },\n },\n [below(theme, compact)]: {\n '--sg-day': rem(theme, M.dayMin.scrolled),\n '& [data-sg-block]': {\n paddingLeft: rem(theme, M.blockPadding.start),\n paddingRight: rem(theme, M.blockPadding.end),\n },\n // A cell the keyboard reaches is brought out beside the pinned names, never under them.\n '& > [data-sg-scroll]': {\n overflowX: 'auto',\n overscrollBehaviorX: 'contain',\n scrollPaddingInlineStart: `calc(var(--sg-name) + ${rem(theme, M.gap)})`,\n },\n // The header row follows the days sideways (the grid sets its scroll). It is no scroller of\n // its own: a scroller with nothing focusable inside is a tab stop of its own.\n // `contain` still holds on a hidden overflow: a sideways swipe over the header is never the\n // browser's back / forward gesture.\n '& > [data-sg-head]': { overflowX: 'hidden', overscrollBehaviorX: 'contain' },\n // The pinned column: the names (and the cell above them, and the group\n // titles) stay while the days scroll under them.\n '& [role=\"rowheader\"], & [data-sg-corner]': {\n position: 'sticky',\n left: 0,\n zIndex: 2,\n backgroundColor: theme.palette.background.default,\n // Covers the gap after it too, so nothing scrolling shows between the name and the days.\n boxShadow: `${rem(theme, M.gap)} 0 0 ${theme.palette.background.default}`,\n },\n '& [data-sg-group-title]': { position: 'sticky', left: 0, width: 'fit-content' },\n },\n [below(theme, M.narrowBelow)]: {\n '--sg-name': rem(theme, M.nameColumn.narrow),\n '--sg-day': rem(theme, M.dayMin.narrow),\n // A phone-sized pane is read and tapped, not dragged (a phone renders\n // DayRuler per day): the grips would eat the block (Shift+arrows still copy).\n '& [data-sg-grip]': { display: 'none' },\n '& [data-sg-block]': { paddingLeft: rem(theme, M.cellPadding), paddingRight: rem(theme, M.cellPadding) },\n },\n display: 'flex',\n flexDirection: 'column',\n minWidth: 0,\n userSelect: 'none',\n };\n };\n}\n\n/** The body: scrolls sideways (under the compact bound) when the days' minimums do not fit. */\nexport const scrollSx: SxProps<Theme> = { minWidth: 0 };\n\n/** One line of the grid — the header or a person — as the shared columns. */\n/** A style that may sit in an `sx` array next to another. */\ntype SxPart = (theme: Theme) => CSSObject;\n\nexport function rowGridSx(dayCount: number, hasTotal: boolean): SxPart {\n return (theme: Theme) => ({\n display: 'grid',\n gridTemplateColumns: `var(--sg-name) repeat(${dayCount}, minmax(var(--sg-day), 1fr))${hasTotal ? ' var(--sg-total)' : ''}`,\n gap: rem(theme, M.gap),\n alignItems: 'stretch',\n minWidth: 'var(--sg-min)',\n });\n}\n\n/**\n * Around the header row: opaque, pinned to the top of the PAGE (or whatever\n * scrolls the grid vertically) — it is not inside the sideways scroller, so\n * it sticks at every width; while the days scroll it follows them sideways.\n */\nexport function headerSx(stickyTop: number): SxPart {\n return (theme: Theme) => ({\n position: 'sticky',\n top: rem(theme, stickyTop),\n zIndex: 3,\n backgroundColor: theme.palette.background.default,\n });\n}\n\n/** The header row itself, inside its sticky frame. */\nexport const headerRowSx: SxPart = (theme: Theme) => ({\n paddingTop: theme.spacing(0.75),\n paddingBottom: theme.spacing(0.75),\n});\n\n/** A day's header: today's label in the primary colour, a gone day's in the secondary ink (today wins). */\nexport function headerCellSx(today: boolean, past = false): SxProps<Theme> {\n let color = 'text.primary';\n if (past) color = 'text.secondary';\n if (today) color = 'primary.main';\n return {\n fontSize: sxRem(M.headerLabel),\n fontWeight: 500,\n color,\n p: 0.5,\n minWidth: 0,\n // A long label (\"Hoje · Seg 19/10\") wraps to a second line, as the prototype's: never cut.\n '& > *': { display: 'block', overflowWrap: 'anywhere' },\n };\n}\n\nexport const headerSublabelSx: SxProps<Theme> = {\n fontSize: sxRem(M.headerSublabel),\n fontWeight: 400,\n color: 'text.secondary',\n};\n\nexport const totalHeaderSx: SxProps<Theme> = {\n fontSize: sxRem(M.total),\n color: 'text.secondary',\n textAlign: 'right',\n alignSelf: 'end',\n p: 0.5,\n pr: 0,\n};\n\nexport const groupTitleSx: SxProps<Theme> = {\n fontSize: sxRem(M.groupTitle),\n letterSpacing: '0.05em',\n textTransform: 'uppercase',\n color: 'text.secondary',\n fontWeight: 500,\n pt: 1.5,\n pb: 0.5,\n m: 0,\n};\n\n/** A person's line: one grid row, then the gap below it. */\nexport const personRowSx: SxPart = (theme: Theme) => ({ marginBottom: rem(theme, M.gap) });\n\nexport const nameCellSx: SxProps<Theme> = {\n display: 'flex',\n flexDirection: 'column',\n justifyContent: 'center',\n pr: 0.5,\n minWidth: 0,\n};\n\nexport const totalCellSx: SxProps<Theme> = {\n fontSize: sxRem(M.total),\n color: 'text.secondary',\n textAlign: 'right',\n alignSelf: 'center',\n whiteSpace: 'nowrap',\n};\n\n/** What a cell is drawing right now. */\nexport interface CellLook {\n today: boolean;\n blocked: boolean;\n /** The day has gone (`closed`): no fill, the divider border; never a drop target. */\n closed: boolean;\n /** A create or copy will land here: dashed, with the hours as ghost text. */\n target: boolean;\n /** The pointer is over it while a block moves. */\n over: boolean;\n /** The cell's own \"+\" button may be pressed. */\n interactive: boolean;\n}\n\nfunction hatch(theme: Theme): string {\n const a = theme.palette.action.hover;\n const b = theme.palette.action.selected;\n const w = rem(theme, M.hatch);\n const w2 = rem(theme, M.hatch * 2);\n return `repeating-linear-gradient(135deg, ${a} 0, ${a} ${w}, ${b} ${w}, ${b} ${w2})`;\n}\n\nexport function cellSx(look: CellLook): SxProps<Theme> {\n return (theme: Theme): CSSObject => {\n const base: CSSObject = {\n position: 'relative',\n minHeight: rem(theme, M.cellMinHeight),\n borderRadius: rem(theme, M.cellRadius),\n backgroundColor: theme.palette.action.hover,\n border: `1px solid ${look.today ? theme.palette.primary.main : theme.palette.divider}`,\n padding: rem(theme, M.cellPadding),\n display: 'flex',\n flexDirection: 'column',\n gap: rem(theme, M.blockGap),\n boxSizing: 'border-box',\n minWidth: 0,\n cursor: look.interactive ? 'cell' : 'default',\n };\n if (look.blocked) {\n return { ...base, background: hatch(theme), borderColor: theme.palette.divider, cursor: 'not-allowed' };\n }\n if (look.closed) return { ...base, backgroundColor: 'transparent', borderColor: theme.palette.divider };\n if (look.target) {\n return {\n ...base,\n border: `${rem(theme, M.targetBorder)} dashed ${theme.palette.primary.main}`,\n backgroundColor: theme.palette.action.selected,\n };\n }\n if (look.over) return { ...base, borderColor: theme.palette.primary.main, backgroundColor: theme.palette.action.selected };\n return base;\n };\n}\n\n/** The empty cell's button: the whole cell, a quiet \"+\" in its middle. */\nexport const plusButtonSx: SxProps<Theme> = (theme: Theme) => ({\n flex: '1 1 auto',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n font: 'inherit',\n background: 'transparent',\n border: 0,\n p: 0,\n m: 0,\n color: theme.palette.text.disabled,\n cursor: 'inherit',\n borderRadius: rem(theme, M.cellRadius - M.cellPadding),\n '& svg': { fontSize: rem(theme, M.plusIcon) },\n // The \"+\" is swapped for the ghost on pointer down: were it the press's\n // target, the browser would drop the click once it left the DOM.\n '& > *': { pointerEvents: 'none' },\n '&:hover': { color: theme.palette.text.secondary },\n '&:focus-visible': { outline: `${rem(theme, M.ring)} solid ${theme.palette.primary.main}`, outlineOffset: 0 },\n // A drag's ghost text sits where the prototype writes it: top left.\n '&[data-ghost]': { justifyContent: 'flex-start', alignItems: 'flex-start' },\n});\n\n/** The ghost text of a cell a create or copy will land on. */\nexport const ghostSx: SxProps<Theme> = (theme: Theme) => ({\n fontSize: rem(theme, M.blockFont),\n fontWeight: 500,\n color: theme.palette.primary.main,\n px: 0.75,\n py: 0.5,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n});\n\n/** A closed day's word (\"Afastamento\"): one line inside its cell, cut with an ellipsis (the full word in `title`). */\nexport const blockedLabelSx: SxProps<Theme> = (theme: Theme) => ({\n display: 'block',\n fontSize: rem(theme, M.blockFont),\n color: theme.palette.text.secondary,\n px: 0.75,\n py: 0.5,\n lineHeight: 1.3,\n minWidth: 0,\n maxWidth: '100%',\n boxSizing: 'border-box',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n});\n\nexport function blockSx(tone: ScheduleBlockTone, opts: { selected: boolean; movable: boolean }): SxProps<Theme> {\n return (theme: Theme): CSSObject => ({\n ...blockToneStyles(theme, tone),\n position: 'relative',\n display: 'block',\n width: '100%',\n minWidth: 0,\n maxWidth: '100%',\n boxSizing: 'border-box',\n textAlign: 'left',\n font: 'inherit',\n fontSize: rem(theme, M.blockFont),\n fontWeight: 500,\n lineHeight: 1.35,\n borderRadius: rem(theme, M.blockRadius),\n padding: `${rem(theme, M.blockPadding.y)} ${rem(theme, M.blockPadding.end)} ${rem(theme, M.blockPadding.y)} ${rem(theme, M.blockPadding.start)}`,\n cursor: opts.movable ? 'grab' : 'pointer',\n margin: 0,\n boxShadow: opts.selected ? `0 0 0 ${rem(theme, M.ring)} ${theme.palette.primary.main}` : 'none',\n '&:focus-visible': { outline: `${rem(theme, M.ring)} solid ${theme.palette.primary.main}`, outlineOffset: rem(theme, M.ringOffset) },\n // The hours stay on one line; the note wraps (the block grows), as the prototype's\n // \"↻ a cada 2 / semanas\": a note is never cut, so a break keeps its end.\n '& > [data-sg-line]': { position: 'relative', display: 'block' },\n '& > [data-sg-line=\"label\"]': { overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' },\n '& > [data-sg-line=\"note\"]': { fontWeight: 400, overflowWrap: 'anywhere' },\n });\n}\n\n/** A break inside a block: a hatched band across its height, under its text. */\nexport function breakSx(span: { start: number; end: number }): SxProps<Theme> {\n return (theme: Theme) => ({\n position: 'absolute',\n top: 0,\n bottom: 0,\n left: `${span.start * 100}%`,\n width: `${(span.end - span.start) * 100}%`,\n background: breakHatch(theme, rem(theme, M.breakStripe.ink), rem(theme, M.breakStripe.ink + M.breakStripe.gap)),\n pointerEvents: 'none',\n });\n}\n\nexport function gripSx(side: 'l' | 'r'): SxProps<Theme> {\n return (theme: Theme) => ({\n position: 'absolute',\n top: 0,\n bottom: 0,\n [side === 'l' ? 'left' : 'right']: 0,\n width: rem(theme, M.grip.width),\n cursor: 'ew-resize',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n '&::before': {\n content: '\"\"',\n display: 'block',\n width: rem(theme, M.grip.barWidth),\n height: rem(theme, M.grip.barHeight),\n borderRadius: rem(theme, M.grip.barRadius),\n backgroundColor: 'currentColor',\n opacity: 0.5,\n },\n });\n}\n\nexport const skeletonCellSx: SxProps<Theme> = (theme: Theme) => ({\n minHeight: rem(theme, M.cellMinHeight),\n borderRadius: rem(theme, M.cellRadius),\n backgroundColor: theme.palette.action.hover,\n});\n\nexport const SR_ONLY_SX: SxProps<Theme> = {\n position: 'absolute',\n width: sxRem(1),\n height: sxRem(1),\n padding: 0,\n margin: sxRem(-1),\n overflow: 'hidden',\n clip: 'rect(0, 0, 0, 0)',\n whiteSpace: 'nowrap',\n border: 0,\n};\n"],"mappings":"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","names":[]}
@@ -1,7 +1,7 @@
1
1
  import "../chunk-TTRWOI6Z.js";
2
2
  import {
3
3
  DayRuler
4
- } from "../chunk-D6JKCCRQ.js";
4
+ } from "../chunk-MLIBJWQZ.js";
5
5
  import "../chunk-MAYAJXO6.js";
6
6
  import "../chunk-IP424VZD.js";
7
7
  import "../chunk-EEK2NK4W.js";
@@ -11,7 +11,7 @@ import "../chunk-7ZQ3KQ7J.js";
11
11
  import "../chunk-YMYJO2CZ.js";
12
12
  import "../chunk-AC7K7IJE.js";
13
13
  import "../chunk-6HZYRKOB.js";
14
- import "../chunk-YSUJCKEE.js";
14
+ import "../chunk-WMTW4JXT.js";
15
15
  import "../chunk-3R6BR22L.js";
16
16
  import "../chunk-YE44HUFF.js";
17
17
  import "../chunk-35HMJQLO.js";
@@ -1,15 +1,15 @@
1
1
  import "../chunk-7RXL4ONS.js";
2
2
  import {
3
3
  ScheduleGrid
4
- } from "../chunk-WCETCAZO.js";
5
- import "../chunk-QQFFE3CQ.js";
6
- import "../chunk-I7CVC2DW.js";
4
+ } from "../chunk-UIJU5X26.js";
5
+ import "../chunk-MPUOLKFT.js";
6
+ import "../chunk-ARPOWDEO.js";
7
7
  import "../chunk-GONPUJIE.js";
8
- import "../chunk-B3SL5FP2.js";
9
- import "../chunk-MQVYJVKV.js";
8
+ import "../chunk-WBMLMLXP.js";
9
+ import "../chunk-E6UMTR2G.js";
10
10
  import "../chunk-AC7K7IJE.js";
11
11
  import "../chunk-6HZYRKOB.js";
12
- import "../chunk-YSUJCKEE.js";
12
+ import "../chunk-WMTW4JXT.js";
13
13
  import "../chunk-3R6BR22L.js";
14
14
  import "../chunk-YE44HUFF.js";
15
15
  import "../chunk-35HMJQLO.js";
@@ -1 +1 @@
1
- {"version":3,"file":"ScheduleGrid.parts.d.ts","sourceRoot":"","sources":["../../../../../src/components/data-display/ScheduleGrid/ScheduleGrid.parts.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AAEpC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAqB/D,OAAO,KAAK,EAEV,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,EACjB,eAAe,EAChB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE3D,8DAA8D;AAC9D,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,OAAO,CAAC;CACf;AAED,+CAA+C;AAC/C,KAAK,KAAK,GAAG,CAAC,KAAK,EAAE,KAAK,KAAK,SAAS,CAAC;AAEzC,UAAU,SAAS;IACjB,GAAG,EAAE,eAAe,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,kBAAkB,CAAC;IAC3B,IAAI,EAAE,gBAAgB,CAAC;IACvB,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC;IACtB,OAAO,EAAE,WAAW,CAAC;IACrB,GAAG,EAAE,aAAa,CAAC;IACnB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IAC1C,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACnD,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,MAAM,EAAE,kBAAkB,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;CAChB;AAyHD,2FAA2F;AAC3F,wBAAgB,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAqC5D;AAQD,UAAU,WAAW;IACnB,OAAO,EAAE,SAAS,kBAAkB,EAAE,CAAC;IACvC,+CAA+C;IAC/C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,KAAK,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AASD,wBAAgB,UAAU,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,WAAW,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAwBjG;AAED,UAAU,SAAS;IACjB,IAAI,EAAE,iBAAiB,CAAC;IACxB,IAAI,EAAE,SAAS,eAAe,EAAE,CAAC;IACjC,KAAK,EAAE,KAAK,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,GAAG,EAAE,aAAa,CAAC;IACnB,OAAO,EAAE,WAAW,CAAC;IACrB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;CAChB;AA0DD,gGAAgG;AAChG,wBAAgB,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,GAAG,IAAI,CAqBlE"}
1
+ {"version":3,"file":"ScheduleGrid.parts.d.ts","sourceRoot":"","sources":["../../../../../src/components/data-display/ScheduleGrid/ScheduleGrid.parts.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AAEpC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAuB/D,OAAO,KAAK,EAEV,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,EACjB,eAAe,EAChB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE3D,8DAA8D;AAC9D,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,OAAO,CAAC;CACf;AAED,+CAA+C;AAC/C,KAAK,KAAK,GAAG,CAAC,KAAK,EAAE,KAAK,KAAK,SAAS,CAAC;AAEzC,UAAU,SAAS;IACjB,GAAG,EAAE,eAAe,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,kBAAkB,CAAC;IAC3B,IAAI,EAAE,gBAAgB,CAAC;IACvB,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC;IACtB,OAAO,EAAE,WAAW,CAAC;IACrB,GAAG,EAAE,aAAa,CAAC;IACnB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IAC1C,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACnD,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,MAAM,EAAE,kBAAkB,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;CAChB;AAgJD,2FAA2F;AAC3F,wBAAgB,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAgC5D;AAQD,UAAU,WAAW;IACnB,OAAO,EAAE,SAAS,kBAAkB,EAAE,CAAC;IACvC,+CAA+C;IAC/C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,KAAK,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AASD,wBAAgB,UAAU,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,WAAW,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CA6BjG;AAED,UAAU,SAAS;IACjB,IAAI,EAAE,iBAAiB,CAAC;IACxB,IAAI,EAAE,SAAS,eAAe,EAAE,CAAC;IACjC,KAAK,EAAE,KAAK,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,GAAG,EAAE,aAAa,CAAC;IACnB,OAAO,EAAE,WAAW,CAAC;IACrB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;CAChB;AA0DD,gGAAgG;AAChG,wBAAgB,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,GAAG,IAAI,CAqBlE"}
@@ -33,7 +33,8 @@ export declare function rowGridSx(dayCount: number, hasTotal: boolean): SxPart;
33
33
  export declare function headerSx(stickyTop: number): SxPart;
34
34
  /** The header row itself, inside its sticky frame. */
35
35
  export declare const headerRowSx: SxPart;
36
- export declare function headerCellSx(today: boolean): SxProps<Theme>;
36
+ /** A day's header: today's label in the primary colour, a gone day's in the secondary ink (today wins). */
37
+ export declare function headerCellSx(today: boolean, past?: boolean): SxProps<Theme>;
37
38
  export declare const headerSublabelSx: SxProps<Theme>;
38
39
  export declare const totalHeaderSx: SxProps<Theme>;
39
40
  export declare const groupTitleSx: SxProps<Theme>;
@@ -45,6 +46,8 @@ export declare const totalCellSx: SxProps<Theme>;
45
46
  export interface CellLook {
46
47
  today: boolean;
47
48
  blocked: boolean;
49
+ /** The day has gone (`closed`): no fill, the divider border; never a drop target. */
50
+ closed: boolean;
48
51
  /** A create or copy will land here: dashed, with the hours as ghost text. */
49
52
  target: boolean;
50
53
  /** The pointer is over it while a block moves. */
@@ -1 +1 @@
1
- {"version":3,"file":"ScheduleGrid.styles.d.ts","sourceRoot":"","sources":["../../../../../src/components/data-display/ScheduleGrid/ScheduleGrid.styles.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,+BAA+B,CAAC;AACpE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAK/D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAE9D;;;GAGG;AACH,eAAO,MAAM,MAAM,EAAE,OAAO,CAAC,KAAK,CAAgE,CAAC;AAqBnG;;;;;;;;;;;GAWG;AACH,wBAAgB,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CA6D3E;AAED,+FAA+F;AAC/F,eAAO,MAAM,QAAQ,EAAE,OAAO,CAAC,KAAK,CAAmB,CAAC;AAExD,6EAA6E;AAC7E,6DAA6D;AAC7D,KAAK,MAAM,GAAG,CAAC,KAAK,EAAE,KAAK,KAAK,SAAS,CAAC;AAE1C,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,MAAM,CAQrE;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAOlD;AAED,sDAAsD;AACtD,eAAO,MAAM,WAAW,EAAE,MAGxB,CAAC;AAEH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAU3D;AAED,eAAO,MAAM,gBAAgB,EAAE,OAAO,CAAC,KAAK,CAI3C,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,OAAO,CAAC,KAAK,CAOxC,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,OAAO,CAAC,KAAK,CASvC,CAAC;AAEF,4DAA4D;AAC5D,eAAO,MAAM,WAAW,EAAE,MAAgE,CAAC;AAE3F,eAAO,MAAM,UAAU,EAAE,OAAO,CAAC,KAAK,CAMrC,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,OAAO,CAAC,KAAK,CAMtC,CAAC;AAEF,wCAAwC;AACxC,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,6EAA6E;IAC7E,MAAM,EAAE,OAAO,CAAC;IAChB,kDAAkD;IAClD,IAAI,EAAE,OAAO,CAAC;IACd,gDAAgD;IAChD,WAAW,EAAE,OAAO,CAAC;CACtB;AAUD,wBAAgB,MAAM,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,CA6BrD;AAED,0EAA0E;AAC1E,eAAO,MAAM,YAAY,EAAE,OAAO,CAAC,KAAK,CAqBtC,CAAC;AAEH,8DAA8D;AAC9D,eAAO,MAAM,OAAO,EAAE,OAAO,CAAC,KAAK,CASjC,CAAC;AAEH,sHAAsH;AACtH,eAAO,MAAM,cAAc,EAAE,OAAO,CAAC,KAAK,CAaxC,CAAC;AAEH,wBAAgB,OAAO,CAAC,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE;IAAE,QAAQ,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,KAAK,CAAC,CA0B9G;AAED,gFAAgF;AAChF,wBAAgB,OAAO,CAAC,IAAI,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,KAAK,CAAC,CAU5E;AAED,wBAAgB,MAAM,CAAC,IAAI,EAAE,GAAG,GAAG,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,CAqBtD;AAED,eAAO,MAAM,cAAc,EAAE,OAAO,CAAC,KAAK,CAIxC,CAAC;AAEH,eAAO,MAAM,UAAU,EAAE,OAAO,CAAC,KAAK,CAUrC,CAAC"}
1
+ {"version":3,"file":"ScheduleGrid.styles.d.ts","sourceRoot":"","sources":["../../../../../src/components/data-display/ScheduleGrid/ScheduleGrid.styles.ts"],"names":[],"mappings":"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"}
@@ -18,6 +18,12 @@ export interface ScheduleGridColumn {
18
18
  sublabel?: string;
19
19
  /** Today's column: its label in the primary colour and its cells framed. */
20
20
  today?: boolean;
21
+ /**
22
+ * The day has gone: its label in the secondary ink (`today` wins). The
23
+ * header only — the cells that can take no new turno say so themselves
24
+ * (`ScheduleGridCell.closed`).
25
+ */
26
+ past?: boolean;
21
27
  }
22
28
  /** A row: one person (or resource) across the days. */
23
29
  export interface ScheduleGridRow {
@@ -87,6 +93,20 @@ export interface ScheduleGridCell {
87
93
  blocked?: boolean;
88
94
  /** Written in a blocked cell with no blocks ("Afastamento"). */
89
95
  blockedLabel?: string;
96
+ /**
97
+ * The day can take no new turno (it has gone). No "+", the empty cell is no
98
+ * focus stop, a create or copy drag skips it and a move or keyboard
99
+ * copy/move onto it is refused — as on a `blocked` day — but with no hatch
100
+ * and no label: the cell just looks empty. Blocks already there still show
101
+ * and still open. Drawn with no fill, only the divider border.
102
+ */
103
+ closed?: boolean;
104
+ /**
105
+ * A closed cell's words for a screen reader ("Já passou"), visually hidden;
106
+ * nothing on screen. Without it the cell stays unnamed. Ignored on a
107
+ * `blocked` cell, which has its own name.
108
+ */
109
+ closedLabel?: string;
90
110
  }
91
111
  export interface ScheduleGridProps {
92
112
  /** The day columns, in order (seven for a week). A day is its index here. */
@@ -103,12 +123,12 @@ export interface ScheduleGridProps {
103
123
  readOnly?: boolean;
104
124
  /**
105
125
  * A click on an empty cell (one day), or a drag across empty cells of one
106
- * row (every crossed day that is empty and not blocked).
126
+ * row (every crossed day that is empty, not blocked and not closed).
107
127
  */
108
128
  onCreate?: (rowId: string, days: number[]) => void;
109
- /** A block's edge grip dragged along its row: the crossed days that are empty and not blocked. */
129
+ /** A block's edge grip dragged along its row: the crossed days that are empty, not blocked and not closed. */
110
130
  onCopy?: (blockId: string, days: number[]) => void;
111
- /** A block's middle dropped on an empty, open cell of any row. */
131
+ /** A block's middle dropped on an empty, open cell of any row (never a blocked or closed one). */
112
132
  onMove?: (blockId: string, toRowId: string, toDay: number) => void;
113
133
  /** A block clicked, tapped or Entered. */
114
134
  onBlockClick?: (blockId: string) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"ScheduleGrid.types.d.ts","sourceRoot":"","sources":["../../../../../src/components/data-display/ScheduleGrid/ScheduleGrid.types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ScheduleGrid.types.d.ts","sourceRoot":"","sources":["../../../../../src/components/data-display/ScheduleGrid/ScheduleGrid.types.ts"],"names":[],"mappings":"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"}
@@ -3,7 +3,7 @@ import type { ScheduleGridCell } from './ScheduleGrid.types';
3
3
  * THE GRID'S RULES, as pure functions (FUT-3825): which days a gesture lands
4
4
  * on. The host decides everything else — hours, limits, refusals.
5
5
  */
6
- /** A cell that can take a new turno: nothing in it and not closed to the row. */
6
+ /** A cell that can take a new turno: nothing in it, not closed to the row (`blocked`) and not gone (`closed`). */
7
7
  export declare function isOpen(cell: ScheduleGridCell): boolean;
8
8
  /** Every day from `a` to `b` inclusive, in order, whichever is larger. */
9
9
  export declare function daysBetween(a: number, b: number): number[];
@@ -1 +1 @@
1
- {"version":3,"file":"schedule-grid-model.d.ts","sourceRoot":"","sources":["../../../../../src/components/data-display/ScheduleGrid/schedule-grid-model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE7D;;;GAGG;AAEH,iFAAiF;AACjF,wBAAgB,MAAM,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAEtD;AAED,0EAA0E;AAC1E,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAI1D;AAED,0FAA0F;AAC1F,wBAAgB,aAAa,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,gBAAgB,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAElH;AAED,sHAAsH;AACtH,wBAAgB,WAAW,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,gBAAgB,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAEhH;AAED,kEAAkE;AAClE,wBAAgB,OAAO,CAAC,MAAM,EAAE,gBAAgB,EAAE,QAAQ,EAAE,OAAO,GAAG,OAAO,CAE5E;AAED,yFAAyF;AACzF,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAG5F"}
1
+ {"version":3,"file":"schedule-grid-model.d.ts","sourceRoot":"","sources":["../../../../../src/components/data-display/ScheduleGrid/schedule-grid-model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE7D;;;GAGG;AAEH,kHAAkH;AAClH,wBAAgB,MAAM,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAEtD;AAED,0EAA0E;AAC1E,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAI1D;AAED,0FAA0F;AAC1F,wBAAgB,aAAa,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,gBAAgB,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAElH;AAED,sHAAsH;AACtH,wBAAgB,WAAW,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,gBAAgB,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAEhH;AAED,kEAAkE;AAClE,wBAAgB,OAAO,CAAC,MAAM,EAAE,gBAAgB,EAAE,QAAQ,EAAE,OAAO,GAAG,OAAO,CAE5E;AAED,yFAAyF;AACzF,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAG5F"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@12-apps/ui",
3
- "version": "6.87.0",
3
+ "version": "6.88.0",
4
4
  "license": "MIT",
5
5
  "packageManager": "pnpm@10.34.5",
6
6
  "type": "module",
@@ -23,8 +23,8 @@ lists events on one axis). For one day by the hour, or for a phone, use `DayRule
23
23
  | gesture | pointer (mouse, pen) | keyboard | reports |
24
24
  |---|---|---|---|
25
25
  | create one day | click an empty cell | Enter on its "+" | `onCreate(rowId, [day])` |
26
- | create several | drag across cells of ONE row | — | `onCreate(rowId, days)` — the crossed days that are empty and not blocked |
27
- | copy | drag a block's left or right edge grip along its row | Shift+← / Shift+→ | `onCopy(blockId, days)` — never its own day, a taken or a blocked one |
26
+ | create several | drag across cells of ONE row | — | `onCreate(rowId, days)` — the crossed days that are empty, not blocked and not closed |
27
+ | copy | drag a block's left or right edge grip along its row | Shift+← / Shift+→ | `onCopy(blockId, days)` — never its own day, a taken, a blocked or a closed one |
28
28
  | move | drag a block's middle to another cell (any row) | Alt+← / Alt+→ | `onMove(blockId, toRowId, toDay)` — only onto an empty, open cell |
29
29
  | open | click a block | Enter | `onBlockClick(blockId)` |
30
30
  | focus | — | ← → ↑ ↓ to the nearest cell with something to focus | — |
@@ -48,9 +48,9 @@ lists events on one axis). For one day by the hour, or for a phone, use `DayRule
48
48
 
49
49
  | Prop | Type | Description |
50
50
  |---|---|---|
51
- | `columns` | `ScheduleGridColumn[]` | `label` (wraps to a second line when its column is short, never cut, and never between a word and the number after it: "Seg 19/10" stays whole; also in `title`), `sublabel?`, `today?` (label in the primary colour, cells framed). A day is its index here. |
51
+ | `columns` | `ScheduleGridColumn[]` | `label` (wraps to a second line when its column is short, never cut, and never between a word and the number after it: "Seg 19/10" stays whole; also in `title`), `sublabel?`, `today?` (label in the primary colour, cells framed), `past?` (the day has gone: label in `text.secondary`, see [Closed days](#closed-days)). A day is its index here. |
52
52
  | `groups` | `ScheduleGridGroup[]` | `title?` (upper-case heading, names the row group), `rows`: `id`, `label`, `meta?`, `metaTone?` (`'warning'` for "acima de 40h"), `total?`, `onLabelClick?` (makes the name a button), `labelAccessible?`, `nameAdornment?` (node beside the name — a "Freela" tag; it moves under the name when the column has no room for both), `chips?` (node under the meta — "2 regras ›"; one line, a chip that does not fit shrinks and cuts its label). |
53
- | `cell` | `(rowId, day) => ScheduleGridCell` | `blocks` (`id`, `label`, `note?`, `tone`, `movable?`, `copyable?`, `selected?`, `title?`, `breakSpan?` — `{ start, end }` as fractions 0…1 of the block, a meal break drawn as a hatched gap; its words go in `note`), `blocked?` (hatched, refuses create and drop), `blockedLabel?`. Called for every cell on each render: keep it cheap. |
53
+ | `cell` | `(rowId, day) => ScheduleGridCell` | `blocks` (`id`, `label`, `note?`, `tone`, `movable?`, `copyable?`, `selected?`, `title?`, `breakSpan?` — `{ start, end }` as fractions 0…1 of the block, a meal break drawn as a hatched gap; its words go in `note`), `blocked?` (hatched, refuses create and drop), `blockedLabel?`, `closed?` (the day can take no new turno — it has gone: no fill, no "+", see [Closed days](#closed-days)), `closedLabel?` (a closed cell's visually hidden words, "Já passou"). Called for every cell on each render: keep it cheap. |
54
54
  | `totalLabel` | `string?` | The last column's header ("horas"). |
55
55
  | `readOnly` | `boolean?` | No "+", no grips, no drag; empty cells are not focusable. Block clicks still reach `onBlockClick`. |
56
56
  | `onCreate` / `onCopy` / `onMove` / `onBlockClick` | see Gestures | Each gesture is offered only when its handler is given. |
@@ -82,6 +82,36 @@ block's height, under its text, so the block reads as cut there in every tone; i
82
82
  `nameAdornment` and `chips` are the host's nodes (an `@12-apps/ui` `Chip` fits): the grid only
83
83
  places them.
84
84
 
85
+ ## Closed days
86
+
87
+ A week runs Monday to Sunday, so the one shown often holds days already gone, and the server
88
+ refuses a turno on them. The host marks such a cell `closed: true`, and the grid offers nothing
89
+ there that could never work:
90
+
91
+ - no "+": the empty cell is not a focus stop (Tab and the arrows pass over it);
92
+ - a create or copy drag across it skips it, and a move or a keyboard copy/move onto it is
93
+ refused (read aloud as for a taken day) — the same rules as a `blocked` day; a move passing
94
+ over it does not highlight it;
95
+ - the blocks already there still show, still open (`onBlockClick`), and still copy and move
96
+ OUT of the day — only the day a turno lands on must be open;
97
+ - no fill: a transparent ground inside the `divider` border, so a run of gone days (a phone's
98
+ first screen can hold nothing else) reads as quiet, not as broken cells. No hatch and no
99
+ visible text;
100
+ - `closedLabel` ("Já passou") is the cell's words for a screen reader, in a visually hidden
101
+ span; without it the cell stays unnamed. It is ignored on a `blocked` cell, which has its own
102
+ name.
103
+
104
+ The day's header says it too: a column with `past: true` draws its label in `text.secondary`
105
+ (`today` wins). **`past` is on the column, not derived from the cells**, because the two say
106
+ different things: `past` is a fact of the DAY, the same for every row, while `closed` is a
107
+ per-row decision the host makes (a back office may still open a gone day to one person, or a
108
+ gone day may hold only blocks). Deriving the header from the cells would make it ask every row
109
+ on each render and pick a rule for a day closed to some rows only. A host showing a gone day
110
+ normally sets both: `past` on its column and `closed` on its cells.
111
+
112
+ `blocked` is the other closed cell: an afastamento, hatched and named. A cell may be both; the
113
+ hatch wins.
114
+
85
115
  ## Layout
86
116
 
87
117
  - Name column 200px · the day columns share the rest equally (`minmax(0, 1fr)`) · total 56px;
@@ -119,7 +149,7 @@ places them.
119
149
  rows only, so the host's `error` and `empty` nodes sit in one full-width row's cell. Every empty
120
150
  cell's "+" and every block is a native `<button>` (Tab, Enter, Space); blocks declare their
121
151
  shortcuts in `aria-keyshortcuts`, and the `selected` block is `aria-current="true"`. A blocked
122
- cell is named by `blockedLabel` (or `labels.blockedCell`). The live region is `role="status"`,
152
+ cell is named by `blockedLabel` (or `labels.blockedCell`); a closed one carries its `closedLabel`, when given, as visually hidden text. The live region is `role="status"`,
123
153
  polite, and stays mounted: each sentence clears it and is written on the next frame, so the
124
154
  same sentence twice is read twice.
125
155
 
@@ -21,9 +21,11 @@ import {
21
21
  personRowSx,
22
22
  plusButtonSx,
23
23
  skeletonCellSx,
24
+ SR_ONLY_SX,
24
25
  totalCellSx,
25
26
  totalHeaderSx,
26
27
  } from './ScheduleGrid.styles';
28
+ import type { CellLook } from './ScheduleGrid.styles';
27
29
  import type {
28
30
  ScheduleGridBlock,
29
31
  ScheduleGridCell,
@@ -178,18 +180,35 @@ function CellFill({ props, ghost }: { props: CellProps; ghost: string | null }):
178
180
  );
179
181
  }
180
182
 
181
- /** One day of one row: its blocks, a "+" when it is empty, the hatch when it is closed. */
182
- export function GridCell(props: CellProps): React.JSX.Element {
183
- const { row, day, column, cell, drag, can, labels, testId } = props;
184
- const ghost = ghostFor(props);
185
- const blocked = Boolean(cell.blocked);
186
- const look = {
183
+ /** A gone day's words for a screen reader ("Já passou"): visually hidden, and only when the host gives them. */
184
+ function ClosedWords({ cell }: { cell: ScheduleGridCell }): React.JSX.Element | null {
185
+ if (!cell.closed || cell.blocked || !cell.closedLabel) return null;
186
+ return (
187
+ <Box component="span" sx={SR_ONLY_SX}>
188
+ {cell.closedLabel}
189
+ </Box>
190
+ );
191
+ }
192
+
193
+ /** How the cell is drawn right now. */
194
+ function lookOf(props: CellProps, ghost: string | null): CellLook {
195
+ const { row, day, column, cell, drag, can } = props;
196
+ return {
187
197
  today: Boolean(column.today),
188
- blocked,
198
+ blocked: Boolean(cell.blocked),
199
+ closed: Boolean(cell.closed),
189
200
  target: ghost !== null,
190
201
  over: drag?.mode === 'move' && drag.moved && drag.rowId === row.id && drag.day === day,
191
202
  interactive: can.create && isOpen(cell),
192
203
  };
204
+ }
205
+
206
+ /** One day of one row: its blocks, a "+" when it is empty, the hatch when it is closed. */
207
+ export function GridCell(props: CellProps): React.JSX.Element {
208
+ const { row, day, column, cell, can, labels, testId } = props;
209
+ const ghost = ghostFor(props);
210
+ const look = lookOf(props, ghost);
211
+ const blocked = look.blocked;
193
212
  const closedName = blocked && cell.blocks.length === 0 ? (cell.blockedLabel ?? labels.blockedCell(row.label, column.label)) : undefined;
194
213
  return (
195
214
  <Box
@@ -214,6 +233,7 @@ export function GridCell(props: CellProps): React.JSX.Element {
214
233
  />
215
234
  ))}
216
235
  <CellFill props={props} ghost={ghost} />
236
+ <ClosedWords cell={cell} />
217
237
  </Box>
218
238
  );
219
239
  }
@@ -245,7 +265,12 @@ export function GridHeader({ columns, totalLabel, rowSx, testId }: HeaderProps):
245
265
  {/* Above the names: a cell of the header row, with nothing to head. */}
246
266
  <span role="cell" data-sg-corner="" />
247
267
  {columns.map((column, day) => (
248
- <Box role="columnheader" key={`${day}-${column.label}`} sx={headerCellSx(Boolean(column.today))}>
268
+ <Box
269
+ role="columnheader"
270
+ key={`${day}-${column.label}`}
271
+ sx={headerCellSx(Boolean(column.today), Boolean(column.past))}
272
+ data-sg-past={column.past ? '' : undefined}
273
+ >
249
274
  <span data-sg-col="full" title={column.label}>
250
275
  {keepDatesWhole(column.label)}
251
276
  </span>
@@ -143,11 +143,15 @@ export const headerRowSx: SxPart = (theme: Theme) => ({
143
143
  paddingBottom: theme.spacing(0.75),
144
144
  });
145
145
 
146
- export function headerCellSx(today: boolean): SxProps<Theme> {
146
+ /** A day's header: today's label in the primary colour, a gone day's in the secondary ink (today wins). */
147
+ export function headerCellSx(today: boolean, past = false): SxProps<Theme> {
148
+ let color = 'text.primary';
149
+ if (past) color = 'text.secondary';
150
+ if (today) color = 'primary.main';
147
151
  return {
148
152
  fontSize: sxRem(M.headerLabel),
149
153
  fontWeight: 500,
150
- color: today ? 'primary.main' : 'text.primary',
154
+ color,
151
155
  p: 0.5,
152
156
  minWidth: 0,
153
157
  // A long label ("Hoje · Seg 19/10") wraps to a second line, as the prototype's: never cut.
@@ -204,6 +208,8 @@ export const totalCellSx: SxProps<Theme> = {
204
208
  export interface CellLook {
205
209
  today: boolean;
206
210
  blocked: boolean;
211
+ /** The day has gone (`closed`): no fill, the divider border; never a drop target. */
212
+ closed: boolean;
207
213
  /** A create or copy will land here: dashed, with the hours as ghost text. */
208
214
  target: boolean;
209
215
  /** The pointer is over it while a block moves. */
@@ -239,6 +245,7 @@ export function cellSx(look: CellLook): SxProps<Theme> {
239
245
  if (look.blocked) {
240
246
  return { ...base, background: hatch(theme), borderColor: theme.palette.divider, cursor: 'not-allowed' };
241
247
  }
248
+ if (look.closed) return { ...base, backgroundColor: 'transparent', borderColor: theme.palette.divider };
242
249
  if (look.target) {
243
250
  return {
244
251
  ...base,
@@ -21,6 +21,12 @@ export interface ScheduleGridColumn {
21
21
  sublabel?: string;
22
22
  /** Today's column: its label in the primary colour and its cells framed. */
23
23
  today?: boolean;
24
+ /**
25
+ * The day has gone: its label in the secondary ink (`today` wins). The
26
+ * header only — the cells that can take no new turno say so themselves
27
+ * (`ScheduleGridCell.closed`).
28
+ */
29
+ past?: boolean;
24
30
  }
25
31
 
26
32
  /** A row: one person (or resource) across the days. */
@@ -95,6 +101,20 @@ export interface ScheduleGridCell {
95
101
  blocked?: boolean;
96
102
  /** Written in a blocked cell with no blocks ("Afastamento"). */
97
103
  blockedLabel?: string;
104
+ /**
105
+ * The day can take no new turno (it has gone). No "+", the empty cell is no
106
+ * focus stop, a create or copy drag skips it and a move or keyboard
107
+ * copy/move onto it is refused — as on a `blocked` day — but with no hatch
108
+ * and no label: the cell just looks empty. Blocks already there still show
109
+ * and still open. Drawn with no fill, only the divider border.
110
+ */
111
+ closed?: boolean;
112
+ /**
113
+ * A closed cell's words for a screen reader ("Já passou"), visually hidden;
114
+ * nothing on screen. Without it the cell stays unnamed. Ignored on a
115
+ * `blocked` cell, which has its own name.
116
+ */
117
+ closedLabel?: string;
98
118
  }
99
119
 
100
120
  export interface ScheduleGridProps {
@@ -112,12 +132,12 @@ export interface ScheduleGridProps {
112
132
  readOnly?: boolean;
113
133
  /**
114
134
  * A click on an empty cell (one day), or a drag across empty cells of one
115
- * row (every crossed day that is empty and not blocked).
135
+ * row (every crossed day that is empty, not blocked and not closed).
116
136
  */
117
137
  onCreate?: (rowId: string, days: number[]) => void;
118
- /** A block's edge grip dragged along its row: the crossed days that are empty and not blocked. */
138
+ /** A block's edge grip dragged along its row: the crossed days that are empty, not blocked and not closed. */
119
139
  onCopy?: (blockId: string, days: number[]) => void;
120
- /** A block's middle dropped on an empty, open cell of any row. */
140
+ /** A block's middle dropped on an empty, open cell of any row (never a blocked or closed one). */
121
141
  onMove?: (blockId: string, toRowId: string, toDay: number) => void;
122
142
  /** A block clicked, tapped or Entered. */
123
143
  onBlockClick?: (blockId: string) => void;
@@ -5,9 +5,9 @@ import type { ScheduleGridCell } from './ScheduleGrid.types';
5
5
  * on. The host decides everything else — hours, limits, refusals.
6
6
  */
7
7
 
8
- /** A cell that can take a new turno: nothing in it and not closed to the row. */
8
+ /** A cell that can take a new turno: nothing in it, not closed to the row (`blocked`) and not gone (`closed`). */
9
9
  export function isOpen(cell: ScheduleGridCell): boolean {
10
- return !cell.blocked && cell.blocks.length === 0;
10
+ return !cell.blocked && !cell.closed && cell.blocks.length === 0;
11
11
  }
12
12
 
13
13
  /** Every day from `a` to `b` inclusive, in order, whichever is larger. */
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/data-display/ScheduleGrid/ScheduleGrid.parts.tsx"],"sourcesContent":["import AddIcon from '@mui/icons-material/Add';\nimport Box from '@mui/material/Box/index.js';\nimport type { CSSObject, Theme } from '@mui/material/styles/index.js';\nimport type * as React from 'react';\n\nimport type { ScheduleGridLabels } from '../../../copy/labels';\nimport { daysBetween, isOpen } from './schedule-grid-model';\nimport { SCHEDULE_GRID_METRICS } from './ScheduleGrid.metrics';\nimport {\n blockedLabelSx,\n blockSx,\n breakSx,\n cellSx,\n ghostSx,\n gripSx,\n groupTitleSx,\n headerCellSx,\n headerSublabelSx,\n headerRowSx,\n nameCellSx,\n personRowSx,\n plusButtonSx,\n skeletonCellSx,\n totalCellSx,\n totalHeaderSx,\n} from './ScheduleGrid.styles';\nimport type {\n ScheduleGridBlock,\n ScheduleGridCell,\n ScheduleGridColumn,\n ScheduleGridProps,\n ScheduleGridRow,\n} from './ScheduleGrid.types';\nimport { ScheduleNameCell } from './ScheduleNameCell';\nimport type { GridDrag, GridDragApi } from './useGridDrag';\n\n/** What the grid lets a cell do, resolved once per render. */\nexport interface CellAbilities {\n create: boolean;\n copy: boolean;\n move: boolean;\n}\n\n/** A row's shared columns, as an `sx` part. */\ntype RowSx = (theme: Theme) => CSSObject;\n\ninterface CellProps {\n row: ScheduleGridRow;\n day: number;\n column: ScheduleGridColumn;\n cell: ScheduleGridCell;\n drag: GridDrag | null;\n dragApi: GridDragApi;\n can: CellAbilities;\n createPreview?: (rowId: string) => string;\n onCreate?: (rowId: string, days: number[]) => void;\n onBlockClick?: (blockId: string) => void;\n labels: ScheduleGridLabels;\n testId: string;\n}\n\n/** The ghost text this cell shows during a create or copy, or `null` when the gesture does not land here. */\nfunction ghostFor(props: CellProps): string | null {\n const { drag, row, day, cell, createPreview } = props;\n if (!drag || drag.mode === 'move' || drag.rowId !== row.id || !isOpen(cell)) return null;\n if (!daysBetween(drag.anchor, drag.day).includes(day)) return null;\n if (drag.mode === 'copy') return day === drag.anchor ? null : drag.preview;\n return createPreview?.(row.id) ?? '';\n}\n\n/** The keys a block answers to, for `aria-keyshortcuts`. */\nfunction shortcutsOf(movable: boolean, copyable: boolean): string | undefined {\n const keys = [movable ? 'Alt+ArrowLeft Alt+ArrowRight' : '', copyable ? 'Shift+ArrowLeft Shift+ArrowRight' : ''];\n return keys.filter(Boolean).join(' ') || undefined;\n}\n\nconst titleOf = (block: ScheduleGridBlock): string => block.title ?? [block.label, block.note].filter(Boolean).join(' · ');\n\ninterface BlockProps {\n block: ScheduleGridBlock;\n row: ScheduleGridRow;\n day: number;\n can: CellAbilities;\n dragApi: GridDragApi;\n onBlockClick?: (blockId: string) => void;\n testId: string;\n}\n\nfunction Grip({ side, onPointerDown, testId }: { side: 'l' | 'r'; onPointerDown: (event: React.PointerEvent) => void; testId: string }) {\n return <Box component=\"span\" aria-hidden sx={gripSx(side)} onPointerDown={onPointerDown} data-sg-grip=\"\" data-testid={testId} />;\n}\n\n/** The block's break, kept inside it whatever the host sent. */\nfunction BreakBand({ span, testId }: { span: { start: number; end: number }; testId: string }): React.JSX.Element | null {\n const start = Math.min(1, Math.max(0, span.start));\n const end = Math.min(1, Math.max(0, span.end));\n if (!(end > start)) return null;\n return <Box component=\"span\" aria-hidden sx={breakSx({ start, end })} data-sg-break=\"\" data-testid={testId} />;\n}\n\nfunction BlockButton({ block, row, day, can, dragApi, onBlockClick, testId }: BlockProps): React.JSX.Element {\n const movable = can.move && Boolean(block.movable);\n const copyable = can.copy && Boolean(block.copyable);\n const startCopy = (event: React.PointerEvent): void => dragApi.startCopy(event, block.id, row.id, day, block.label);\n const startMove = (event: React.PointerEvent): void => dragApi.startMove(event, block.id, row.id, day);\n return (\n <Box\n component=\"button\"\n type=\"button\"\n sx={blockSx(block.tone, { selected: Boolean(block.selected), movable })}\n title={titleOf(block)}\n aria-keyshortcuts={shortcutsOf(movable, copyable)}\n aria-current={block.selected ? 'true' : undefined}\n data-sg-focus=\"\"\n data-sg-row={row.id}\n data-sg-day={day}\n data-sg-block={block.id}\n data-tone={block.tone}\n data-testid={`${testId}-block-${block.id}`}\n onPointerDown={movable ? startMove : undefined}\n onClick={() => {\n if (!dragApi.takeClick()) onBlockClick?.(block.id);\n }}\n >\n {block.breakSpan ? <BreakBand span={block.breakSpan} testId={`${testId}-break-${block.id}`} /> : null}\n {copyable ? <Grip side=\"l\" onPointerDown={startCopy} testId={`${testId}-grip-l-${block.id}`} /> : null}\n <span data-sg-line=\"label\">{block.label}</span>\n {block.note ? <span data-sg-line=\"note\">{block.note}</span> : null}\n {copyable ? <Grip side=\"r\" onPointerDown={startCopy} testId={`${testId}-grip-r-${block.id}`} /> : null}\n </Box>\n );\n}\n\n/**\n * The empty cell's \"+\". It stays mounted while a drag shows the ghost in it, so\n * a press and release in place is still its click.\n */\nfunction PlusButton({ props, ghost }: { props: CellProps; ghost: string | null }): React.JSX.Element {\n const { row, day, column, dragApi, onCreate, labels } = props;\n return (\n <Box\n component=\"button\"\n type=\"button\"\n sx={plusButtonSx}\n aria-label={labels.createCell(row.label, column.label)}\n data-ghost={ghost === null ? undefined : ''}\n data-sg-focus=\"\"\n data-sg-row={row.id}\n data-sg-day={day}\n onPointerDown={(event: React.PointerEvent) => dragApi.startCreate(event, row.id, day)}\n onClick={() => {\n if (!dragApi.takeClick()) onCreate?.(row.id, [day]);\n }}\n >\n {ghost === null ? <AddIcon aria-hidden /> : <Ghost text={ghost} />}\n </Box>\n );\n}\n\nfunction Ghost({ text }: { text: string }): React.JSX.Element {\n return (\n <Box component=\"span\" sx={ghostSx} aria-hidden>\n {text}\n </Box>\n );\n}\n\n/** What fills a cell after its blocks: the \"+\" (or the ghost in it), a lone ghost, or a closed day's label. */\nfunction CellFill({ props, ghost }: { props: CellProps; ghost: string | null }): React.JSX.Element | null {\n const { cell, can } = props;\n if (can.create && isOpen(cell)) return <PlusButton props={props} ghost={ghost} />;\n if (ghost !== null) return <Ghost text={ghost} />;\n if (!cell.blocked || cell.blocks.length > 0 || !cell.blockedLabel) return null;\n return (\n <Box component=\"span\" sx={blockedLabelSx} aria-hidden title={cell.blockedLabel}>\n {cell.blockedLabel}\n </Box>\n );\n}\n\n/** One day of one row: its blocks, a \"+\" when it is empty, the hatch when it is closed. */\nexport function GridCell(props: CellProps): React.JSX.Element {\n const { row, day, column, cell, drag, can, labels, testId } = props;\n const ghost = ghostFor(props);\n const blocked = Boolean(cell.blocked);\n const look = {\n today: Boolean(column.today),\n blocked,\n target: ghost !== null,\n over: drag?.mode === 'move' && drag.moved && drag.rowId === row.id && drag.day === day,\n interactive: can.create && isOpen(cell),\n };\n const closedName = blocked && cell.blocks.length === 0 ? (cell.blockedLabel ?? labels.blockedCell(row.label, column.label)) : undefined;\n return (\n <Box\n role=\"cell\"\n sx={cellSx(look)}\n data-sg-cell=\"\"\n data-sg-row={row.id}\n data-sg-day={day}\n data-testid={`${testId}-cell-${row.id}-${day}`}\n aria-label={closedName}\n >\n {cell.blocks.map((block) => (\n <BlockButton\n key={block.id}\n block={block}\n row={row}\n day={day}\n can={can}\n dragApi={props.dragApi}\n onBlockClick={props.onBlockClick}\n testId={testId}\n />\n ))}\n <CellFill props={props} ghost={ghost} />\n </Box>\n );\n}\n\n/** The first column: the person, as both views draw it. */\nfunction NameCell({ row }: { row: ScheduleGridRow }): React.JSX.Element {\n const sizes = { name: SCHEDULE_GRID_METRICS.rowName, meta: SCHEDULE_GRID_METRICS.rowMeta, chipsTop: 0.5 };\n return <ScheduleNameCell row={row} role=\"rowheader\" sx={nameCellSx} sizes={sizes} />;\n}\n\ninterface HeaderProps {\n columns: readonly ScheduleGridColumn[];\n /** Present when the grid has a last column. */\n totalLabel?: string;\n rowSx: RowSx;\n testId: string;\n}\n\n/** The days, their counts and the total column's header — pinned while the grid scrolls. */\n\n/** A label wraps between words, never inside \"Seg 19/10\": the space before a number holds. */\nfunction keepDatesWhole(label: string): string {\n return label.replace(/ (?=\\d)/g, '\\u00a0');\n}\n\nexport function GridHeader({ columns, totalLabel, rowSx, testId }: HeaderProps): React.JSX.Element {\n return (\n <Box role=\"row\" sx={[rowSx, headerRowSx]} data-testid={`${testId}-header`}>\n {/* Above the names: a cell of the header row, with nothing to head. */}\n <span role=\"cell\" data-sg-corner=\"\" />\n {columns.map((column, day) => (\n <Box role=\"columnheader\" key={`${day}-${column.label}`} sx={headerCellSx(Boolean(column.today))}>\n <span data-sg-col=\"full\" title={column.label}>\n {keepDatesWhole(column.label)}\n </span>\n {column.sublabel ? (\n <Box component=\"span\" sx={headerSublabelSx} data-sg-col=\"sub\">\n {column.sublabel}\n </Box>\n ) : null}\n </Box>\n ))}\n {totalLabel !== undefined ? (\n <Box role=\"columnheader\" sx={totalHeaderSx}>\n {totalLabel}\n </Box>\n ) : null}\n </Box>\n );\n}\n\ninterface BodyProps {\n grid: ScheduleGridProps;\n rows: readonly ScheduleGridRow[];\n rowSx: RowSx;\n hasTotal: boolean;\n can: CellAbilities;\n dragApi: GridDragApi;\n labels: ScheduleGridLabels;\n testId: string;\n}\n\nfunction SkeletonRows({ grid, rowSx, testId }: Pick<BodyProps, 'grid' | 'rowSx' | 'testId'>): React.JSX.Element {\n return (\n <>\n {Array.from({ length: SCHEDULE_GRID_METRICS.skeletonRows }, (_, index) => (\n <Box key={index} sx={[rowSx, personRowSx]} aria-hidden data-testid={`${testId}-loading`}>\n <Box sx={skeletonCellSx} />\n {grid.columns.map((column, day) => (\n <Box key={`${day}-${column.label}`} sx={skeletonCellSx} />\n ))}\n </Box>\n ))}\n </>\n );\n}\n\nfunction PersonRow({ row, body }: { row: ScheduleGridRow; body: BodyProps }): React.JSX.Element {\n const { grid, rowSx, hasTotal, can, dragApi, labels, testId } = body;\n return (\n <Box role=\"row\" sx={[rowSx, personRowSx]} data-testid={`${testId}-row-${row.id}`}>\n <NameCell row={row} />\n {grid.columns.map((column, day) => (\n <GridCell\n key={`${day}-${column.label}`}\n row={row}\n day={day}\n column={column}\n cell={grid.cell(row.id, day)}\n drag={dragApi.drag}\n dragApi={dragApi}\n can={can}\n createPreview={grid.createPreview}\n onCreate={grid.onCreate}\n onBlockClick={grid.onBlockClick}\n labels={labels}\n testId={testId}\n />\n ))}\n {hasTotal ? (\n <Box role=\"cell\" sx={totalCellSx}>\n {row.total}\n </Box>\n ) : null}\n </Box>\n );\n}\n\n/** The host's error or empty node, as the table's one full-width row (a table holds rows only). */\nfunction MessageRow({ children, testId }: { children: React.ReactNode; testId: string }): React.JSX.Element | null {\n if (children === null || children === undefined || children === false) return null;\n return (\n <Box role=\"row\" data-testid={`${testId}-message`}>\n <Box role=\"cell\">{children}</Box>\n </Box>\n );\n}\n\n/** The groups and their rows — or the skeleton, the host's error, or the host's empty state. */\nexport function GridBody(body: BodyProps): React.JSX.Element | null {\n const { grid, rows } = body;\n if (grid.error) return <MessageRow testId={body.testId}>{grid.error}</MessageRow>;\n if (grid.loading) return <SkeletonRows grid={grid} rowSx={body.rowSx} testId={body.testId} />;\n if (rows.length === 0) return <MessageRow testId={body.testId}>{grid.empty}</MessageRow>;\n return (\n <>\n {grid.groups.map((group, index) => (\n <Box role=\"rowgroup\" key={`${index}-${group.title ?? ''}`} aria-label={group.title}>\n {group.title ? (\n <Box component=\"p\" sx={groupTitleSx} aria-hidden data-sg-group-title=\"\">\n {group.title}\n </Box>\n ) : null}\n {group.rows.map((row) => (\n <PersonRow key={row.id} row={row} body={body} />\n ))}\n </Box>\n ))}\n </>\n );\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/data-display/ScheduleGrid/schedule-grid-model.ts"],"sourcesContent":["import type { ScheduleGridCell } from './ScheduleGrid.types';\n\n/**\n * THE GRID'S RULES, as pure functions (FUT-3825): which days a gesture lands\n * on. The host decides everything else — hours, limits, refusals.\n */\n\n/** A cell that can take a new turno: nothing in it and not closed to the row. */\nexport function isOpen(cell: ScheduleGridCell): boolean {\n return !cell.blocked && cell.blocks.length === 0;\n}\n\n/** Every day from `a` to `b` inclusive, in order, whichever is larger. */\nexport function daysBetween(a: number, b: number): number[] {\n const from = Math.min(a, b);\n const to = Math.max(a, b);\n return Array.from({ length: to - from + 1 }, (_, index) => from + index);\n}\n\n/** A create across `anchor…current` of one row: the crossed days that are open (G-R1). */\nexport function createTargets(cellOf: (day: number) => ScheduleGridCell, anchor: number, current: number): number[] {\n return daysBetween(anchor, current).filter((day) => isOpen(cellOf(day)));\n}\n\n/** A copy of the block on `source` across `source…current`: never its own day, never a taken or closed one (G-R2). */\nexport function copyTargets(cellOf: (day: number) => ScheduleGridCell, source: number, current: number): number[] {\n return daysBetween(source, current).filter((day) => day !== source && isOpen(cellOf(day)));\n}\n\n/** A move may land on an open cell that is not its own (G-R3). */\nexport function canDrop(target: ScheduleGridCell, sameCell: boolean): boolean {\n return !sameCell && isOpen(target);\n}\n\n/** The day one step left (-1) or right (+1) of `day`, or `undefined` past either end. */\nexport function stepDay(day: number, direction: -1 | 1, dayCount: number): number | undefined {\n const next = day + direction;\n return next >= 0 && next < dayCount ? next : undefined;\n}\n"],"mappings":";AAQO,SAAS,OAAO,MAAiC;AACtD,SAAO,CAAC,KAAK,WAAW,KAAK,OAAO,WAAW;AACjD;AAGO,SAAS,YAAY,GAAW,GAAqB;AAC1D,QAAM,OAAO,KAAK,IAAI,GAAG,CAAC;AAC1B,QAAM,KAAK,KAAK,IAAI,GAAG,CAAC;AACxB,SAAO,MAAM,KAAK,EAAE,QAAQ,KAAK,OAAO,EAAE,GAAG,CAAC,GAAG,UAAU,OAAO,KAAK;AACzE;AAGO,SAAS,cAAc,QAA2C,QAAgB,SAA2B;AAClH,SAAO,YAAY,QAAQ,OAAO,EAAE,OAAO,CAAC,QAAQ,OAAO,OAAO,GAAG,CAAC,CAAC;AACzE;AAGO,SAAS,YAAY,QAA2C,QAAgB,SAA2B;AAChH,SAAO,YAAY,QAAQ,OAAO,EAAE,OAAO,CAAC,QAAQ,QAAQ,UAAU,OAAO,OAAO,GAAG,CAAC,CAAC;AAC3F;AAGO,SAAS,QAAQ,QAA0B,UAA4B;AAC5E,SAAO,CAAC,YAAY,OAAO,MAAM;AACnC;AAGO,SAAS,QAAQ,KAAa,WAAmB,UAAsC;AAC5F,QAAM,OAAO,MAAM;AACnB,SAAO,QAAQ,KAAK,OAAO,WAAW,OAAO;AAC/C;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/data-display/ScheduleGrid/ScheduleGrid.styles.ts"],"sourcesContent":["import type { SxProps, Theme } from '@mui/material/styles/index.js';\nimport type { CSSObject } from '@mui/material/styles/index.js';\n\nimport { rem, sxRem } from '../../../tokens/relative';\nimport { SCHEDULE_GRID_METRICS as M } from './ScheduleGrid.metrics';\nimport { blockToneStyles, breakHatch } from './schedule-tones';\nimport type { ScheduleBlockTone } from './ScheduleGrid.types';\n\n/**\n * The grid's root: the container the column widths answer to (container\n * queries, never media queries — the grid may sit in a narrow pane).\n */\nexport const rootSx: SxProps<Theme> = { containerType: 'inline-size', minWidth: 0, width: '100%' };\n\n/** The columns a row has: the name, the days, the total (when there is one). */\nfunction trackCount(dayCount: number, hasTotal: boolean): number {\n return 1 + dayCount + (hasTotal ? 1 : 0);\n}\n\n/**\n * The narrowest container a layout fits in, in px: its name column, its days\n * at their minimum, its total, and the gaps between them — for THIS grid's\n * day count, so a fortnight scrolls where a week still fits.\n */\nfunction fitsFrom(dayCount: number, hasTotal: boolean, name: number, day: number, total: number): number {\n return name + dayCount * day + (hasTotal ? total : 0) + (trackCount(dayCount, hasTotal) - 1) * M.gap;\n}\n\n/** `@container (width < px)`: every bound is \"from px up\" (ranges are exclusive below, inclusive above). */\nfunction below(theme: Theme, px: number): string {\n return `@container (width < ${rem(theme, px)})`;\n}\n\n/**\n * The column widths, as variables every row reads, by the container's width:\n * - from `wide` up: 200px names, days of at least 104px with their grips;\n * - from `compact` up: 140px names, 40px total, days of at least 98px — still\n * unscrolled, grips kept, the header row sticking to the page;\n * - below `compact`: days of at least 152px, grips kept; the body scrolls\n * sideways under the pinned names and the header row follows it sideways\n * while it still sticks to the page (`useSidewaysScroll` sets its scroll);\n * - below 600px: 120px names, 136px days, no grips.\n * The `wide` and `compact` bounds come from this grid's own day count\n * (`fitsFrom`). Container queries, never media queries.\n */\nexport function frameSx(dayCount: number, hasTotal: boolean): SxProps<Theme> {\n return (theme: Theme) => {\n const terms = ['var(--sg-name)', `${dayCount} * var(--sg-day)`, `${trackCount(dayCount, hasTotal) - 1} * ${rem(theme, M.gap)}`];\n if (hasTotal) terms.push('var(--sg-total)');\n const wide = fitsFrom(dayCount, hasTotal, M.nameColumn.wide, M.dayMin.wide, M.totalColumn.wide);\n const compact = fitsFrom(dayCount, hasTotal, M.nameColumn.compact, M.dayMin.compact, M.totalColumn.compact);\n return {\n '--sg-name': rem(theme, M.nameColumn.wide),\n '--sg-total': rem(theme, M.totalColumn.wide),\n '--sg-day': rem(theme, M.dayMin.wide),\n // What every row is at least: its own columns at their minimums.\n '--sg-min': `calc(${terms.join(' + ')})`,\n [below(theme, wide)]: {\n '--sg-name': rem(theme, M.nameColumn.compact),\n '--sg-total': rem(theme, M.totalColumn.compact),\n '--sg-day': rem(theme, M.dayMin.compact),\n '& [data-sg-block]': { paddingLeft: rem(theme, M.blockPadding.tight), paddingRight: rem(theme, M.blockPadding.tight) },\n },\n [below(theme, compact)]: {\n '--sg-day': rem(theme, M.dayMin.scrolled),\n '& [data-sg-block]': {\n paddingLeft: rem(theme, M.blockPadding.start),\n paddingRight: rem(theme, M.blockPadding.end),\n },\n // A cell the keyboard reaches is brought out beside the pinned names, never under them.\n '& > [data-sg-scroll]': {\n overflowX: 'auto',\n overscrollBehaviorX: 'contain',\n scrollPaddingInlineStart: `calc(var(--sg-name) + ${rem(theme, M.gap)})`,\n },\n // The header row follows the days sideways (the grid sets its scroll). It is no scroller of\n // its own: a scroller with nothing focusable inside is a tab stop of its own.\n // `contain` still holds on a hidden overflow: a sideways swipe over the header is never the\n // browser's back / forward gesture.\n '& > [data-sg-head]': { overflowX: 'hidden', overscrollBehaviorX: 'contain' },\n // The pinned column: the names (and the cell above them, and the group\n // titles) stay while the days scroll under them.\n '& [role=\"rowheader\"], & [data-sg-corner]': {\n position: 'sticky',\n left: 0,\n zIndex: 2,\n backgroundColor: theme.palette.background.default,\n // Covers the gap after it too, so nothing scrolling shows between the name and the days.\n boxShadow: `${rem(theme, M.gap)} 0 0 ${theme.palette.background.default}`,\n },\n '& [data-sg-group-title]': { position: 'sticky', left: 0, width: 'fit-content' },\n },\n [below(theme, M.narrowBelow)]: {\n '--sg-name': rem(theme, M.nameColumn.narrow),\n '--sg-day': rem(theme, M.dayMin.narrow),\n // A phone-sized pane is read and tapped, not dragged (a phone renders\n // DayRuler per day): the grips would eat the block (Shift+arrows still copy).\n '& [data-sg-grip]': { display: 'none' },\n '& [data-sg-block]': { paddingLeft: rem(theme, M.cellPadding), paddingRight: rem(theme, M.cellPadding) },\n },\n display: 'flex',\n flexDirection: 'column',\n minWidth: 0,\n userSelect: 'none',\n };\n };\n}\n\n/** The body: scrolls sideways (under the compact bound) when the days' minimums do not fit. */\nexport const scrollSx: SxProps<Theme> = { minWidth: 0 };\n\n/** One line of the grid — the header or a person — as the shared columns. */\n/** A style that may sit in an `sx` array next to another. */\ntype SxPart = (theme: Theme) => CSSObject;\n\nexport function rowGridSx(dayCount: number, hasTotal: boolean): SxPart {\n return (theme: Theme) => ({\n display: 'grid',\n gridTemplateColumns: `var(--sg-name) repeat(${dayCount}, minmax(var(--sg-day), 1fr))${hasTotal ? ' var(--sg-total)' : ''}`,\n gap: rem(theme, M.gap),\n alignItems: 'stretch',\n minWidth: 'var(--sg-min)',\n });\n}\n\n/**\n * Around the header row: opaque, pinned to the top of the PAGE (or whatever\n * scrolls the grid vertically) — it is not inside the sideways scroller, so\n * it sticks at every width; while the days scroll it follows them sideways.\n */\nexport function headerSx(stickyTop: number): SxPart {\n return (theme: Theme) => ({\n position: 'sticky',\n top: rem(theme, stickyTop),\n zIndex: 3,\n backgroundColor: theme.palette.background.default,\n });\n}\n\n/** The header row itself, inside its sticky frame. */\nexport const headerRowSx: SxPart = (theme: Theme) => ({\n paddingTop: theme.spacing(0.75),\n paddingBottom: theme.spacing(0.75),\n});\n\nexport function headerCellSx(today: boolean): SxProps<Theme> {\n return {\n fontSize: sxRem(M.headerLabel),\n fontWeight: 500,\n color: today ? 'primary.main' : 'text.primary',\n p: 0.5,\n minWidth: 0,\n // A long label (\"Hoje · Seg 19/10\") wraps to a second line, as the prototype's: never cut.\n '& > *': { display: 'block', overflowWrap: 'anywhere' },\n };\n}\n\nexport const headerSublabelSx: SxProps<Theme> = {\n fontSize: sxRem(M.headerSublabel),\n fontWeight: 400,\n color: 'text.secondary',\n};\n\nexport const totalHeaderSx: SxProps<Theme> = {\n fontSize: sxRem(M.total),\n color: 'text.secondary',\n textAlign: 'right',\n alignSelf: 'end',\n p: 0.5,\n pr: 0,\n};\n\nexport const groupTitleSx: SxProps<Theme> = {\n fontSize: sxRem(M.groupTitle),\n letterSpacing: '0.05em',\n textTransform: 'uppercase',\n color: 'text.secondary',\n fontWeight: 500,\n pt: 1.5,\n pb: 0.5,\n m: 0,\n};\n\n/** A person's line: one grid row, then the gap below it. */\nexport const personRowSx: SxPart = (theme: Theme) => ({ marginBottom: rem(theme, M.gap) });\n\nexport const nameCellSx: SxProps<Theme> = {\n display: 'flex',\n flexDirection: 'column',\n justifyContent: 'center',\n pr: 0.5,\n minWidth: 0,\n};\n\nexport const totalCellSx: SxProps<Theme> = {\n fontSize: sxRem(M.total),\n color: 'text.secondary',\n textAlign: 'right',\n alignSelf: 'center',\n whiteSpace: 'nowrap',\n};\n\n/** What a cell is drawing right now. */\nexport interface CellLook {\n today: boolean;\n blocked: boolean;\n /** A create or copy will land here: dashed, with the hours as ghost text. */\n target: boolean;\n /** The pointer is over it while a block moves. */\n over: boolean;\n /** The cell's own \"+\" button may be pressed. */\n interactive: boolean;\n}\n\nfunction hatch(theme: Theme): string {\n const a = theme.palette.action.hover;\n const b = theme.palette.action.selected;\n const w = rem(theme, M.hatch);\n const w2 = rem(theme, M.hatch * 2);\n return `repeating-linear-gradient(135deg, ${a} 0, ${a} ${w}, ${b} ${w}, ${b} ${w2})`;\n}\n\nexport function cellSx(look: CellLook): SxProps<Theme> {\n return (theme: Theme): CSSObject => {\n const base: CSSObject = {\n position: 'relative',\n minHeight: rem(theme, M.cellMinHeight),\n borderRadius: rem(theme, M.cellRadius),\n backgroundColor: theme.palette.action.hover,\n border: `1px solid ${look.today ? theme.palette.primary.main : theme.palette.divider}`,\n padding: rem(theme, M.cellPadding),\n display: 'flex',\n flexDirection: 'column',\n gap: rem(theme, M.blockGap),\n boxSizing: 'border-box',\n minWidth: 0,\n cursor: look.interactive ? 'cell' : 'default',\n };\n if (look.blocked) {\n return { ...base, background: hatch(theme), borderColor: theme.palette.divider, cursor: 'not-allowed' };\n }\n if (look.target) {\n return {\n ...base,\n border: `${rem(theme, M.targetBorder)} dashed ${theme.palette.primary.main}`,\n backgroundColor: theme.palette.action.selected,\n };\n }\n if (look.over) return { ...base, borderColor: theme.palette.primary.main, backgroundColor: theme.palette.action.selected };\n return base;\n };\n}\n\n/** The empty cell's button: the whole cell, a quiet \"+\" in its middle. */\nexport const plusButtonSx: SxProps<Theme> = (theme: Theme) => ({\n flex: '1 1 auto',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n font: 'inherit',\n background: 'transparent',\n border: 0,\n p: 0,\n m: 0,\n color: theme.palette.text.disabled,\n cursor: 'inherit',\n borderRadius: rem(theme, M.cellRadius - M.cellPadding),\n '& svg': { fontSize: rem(theme, M.plusIcon) },\n // The \"+\" is swapped for the ghost on pointer down: were it the press's\n // target, the browser would drop the click once it left the DOM.\n '& > *': { pointerEvents: 'none' },\n '&:hover': { color: theme.palette.text.secondary },\n '&:focus-visible': { outline: `${rem(theme, M.ring)} solid ${theme.palette.primary.main}`, outlineOffset: 0 },\n // A drag's ghost text sits where the prototype writes it: top left.\n '&[data-ghost]': { justifyContent: 'flex-start', alignItems: 'flex-start' },\n});\n\n/** The ghost text of a cell a create or copy will land on. */\nexport const ghostSx: SxProps<Theme> = (theme: Theme) => ({\n fontSize: rem(theme, M.blockFont),\n fontWeight: 500,\n color: theme.palette.primary.main,\n px: 0.75,\n py: 0.5,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n});\n\n/** A closed day's word (\"Afastamento\"): one line inside its cell, cut with an ellipsis (the full word in `title`). */\nexport const blockedLabelSx: SxProps<Theme> = (theme: Theme) => ({\n display: 'block',\n fontSize: rem(theme, M.blockFont),\n color: theme.palette.text.secondary,\n px: 0.75,\n py: 0.5,\n lineHeight: 1.3,\n minWidth: 0,\n maxWidth: '100%',\n boxSizing: 'border-box',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n});\n\nexport function blockSx(tone: ScheduleBlockTone, opts: { selected: boolean; movable: boolean }): SxProps<Theme> {\n return (theme: Theme): CSSObject => ({\n ...blockToneStyles(theme, tone),\n position: 'relative',\n display: 'block',\n width: '100%',\n minWidth: 0,\n maxWidth: '100%',\n boxSizing: 'border-box',\n textAlign: 'left',\n font: 'inherit',\n fontSize: rem(theme, M.blockFont),\n fontWeight: 500,\n lineHeight: 1.35,\n borderRadius: rem(theme, M.blockRadius),\n padding: `${rem(theme, M.blockPadding.y)} ${rem(theme, M.blockPadding.end)} ${rem(theme, M.blockPadding.y)} ${rem(theme, M.blockPadding.start)}`,\n cursor: opts.movable ? 'grab' : 'pointer',\n margin: 0,\n boxShadow: opts.selected ? `0 0 0 ${rem(theme, M.ring)} ${theme.palette.primary.main}` : 'none',\n '&:focus-visible': { outline: `${rem(theme, M.ring)} solid ${theme.palette.primary.main}`, outlineOffset: rem(theme, M.ringOffset) },\n // The hours stay on one line; the note wraps (the block grows), as the prototype's\n // \"↻ a cada 2 / semanas\": a note is never cut, so a break keeps its end.\n '& > [data-sg-line]': { position: 'relative', display: 'block' },\n '& > [data-sg-line=\"label\"]': { overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' },\n '& > [data-sg-line=\"note\"]': { fontWeight: 400, overflowWrap: 'anywhere' },\n });\n}\n\n/** A break inside a block: a hatched band across its height, under its text. */\nexport function breakSx(span: { start: number; end: number }): SxProps<Theme> {\n return (theme: Theme) => ({\n position: 'absolute',\n top: 0,\n bottom: 0,\n left: `${span.start * 100}%`,\n width: `${(span.end - span.start) * 100}%`,\n background: breakHatch(theme, rem(theme, M.breakStripe.ink), rem(theme, M.breakStripe.ink + M.breakStripe.gap)),\n pointerEvents: 'none',\n });\n}\n\nexport function gripSx(side: 'l' | 'r'): SxProps<Theme> {\n return (theme: Theme) => ({\n position: 'absolute',\n top: 0,\n bottom: 0,\n [side === 'l' ? 'left' : 'right']: 0,\n width: rem(theme, M.grip.width),\n cursor: 'ew-resize',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n '&::before': {\n content: '\"\"',\n display: 'block',\n width: rem(theme, M.grip.barWidth),\n height: rem(theme, M.grip.barHeight),\n borderRadius: rem(theme, M.grip.barRadius),\n backgroundColor: 'currentColor',\n opacity: 0.5,\n },\n });\n}\n\nexport const skeletonCellSx: SxProps<Theme> = (theme: Theme) => ({\n minHeight: rem(theme, M.cellMinHeight),\n borderRadius: rem(theme, M.cellRadius),\n backgroundColor: theme.palette.action.hover,\n});\n\nexport const SR_ONLY_SX: SxProps<Theme> = {\n position: 'absolute',\n width: sxRem(1),\n height: sxRem(1),\n padding: 0,\n margin: sxRem(-1),\n overflow: 'hidden',\n clip: 'rect(0, 0, 0, 0)',\n whiteSpace: 'nowrap',\n border: 0,\n};\n"],"mappings":"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","names":[]}