@geomak/ui 6.25.0 → 6.26.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -2877,6 +2877,7 @@ var MONTHS2 = [
2877
2877
  "November",
2878
2878
  "December"
2879
2879
  ];
2880
+ var MONTHS_SHORT = MONTHS2.map((m) => m.slice(0, 3));
2880
2881
  var WEEKDAYS2 = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
2881
2882
  var toDate = (d) => d instanceof Date ? d : new Date(d);
2882
2883
  var startOfDay2 = (d) => new Date(d.getFullYear(), d.getMonth(), d.getDate());
@@ -3004,10 +3005,18 @@ function Scheduler({
3004
3005
  /* @__PURE__ */ jsxRuntime.jsx(IconButton, { type: "bordered", size: "sm", icon: /* @__PURE__ */ jsxRuntime.jsx(Chevron4, { dir: "left" }), title: "Previous", onClick: () => go(-1) }),
3005
3006
  /* @__PURE__ */ jsxRuntime.jsx(IconButton, { type: "bordered", size: "sm", icon: /* @__PURE__ */ jsxRuntime.jsx(Chevron4, { dir: "right" }), title: "Next", onClick: () => go(1) }),
3006
3007
  /* @__PURE__ */ jsxRuntime.jsx(Button_default, { variant: "ghost", size: "sm", content: "Today", onClick: goToday }),
3007
- /* @__PURE__ */ jsxRuntime.jsxs("h2", { className: "ml-1 min-w-[9rem] text-base font-semibold tracking-tight text-foreground", children: [
3008
- title,
3009
- loading && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-2 inline-flex translate-y-0.5", children: /* @__PURE__ */ jsxRuntime.jsx(Spinner2, {}) })
3010
- ] })
3008
+ /* @__PURE__ */ jsxRuntime.jsx(
3009
+ MonthYearPicker,
3010
+ {
3011
+ label: title,
3012
+ cursor,
3013
+ onPick: (d) => {
3014
+ setDir(0);
3015
+ setCursor(d);
3016
+ }
3017
+ }
3018
+ ),
3019
+ loading && /* @__PURE__ */ jsxRuntime.jsx(Spinner2, {})
3011
3020
  ] }),
3012
3021
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
3013
3022
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -3058,6 +3067,64 @@ function Scheduler({
3058
3067
  }
3059
3068
  );
3060
3069
  }
3070
+ function MonthYearPicker({ label, cursor, onPick }) {
3071
+ const [open, setOpen] = React29.useState(false);
3072
+ const [viewYear, setViewYear] = React29.useState(cursor.getFullYear());
3073
+ React29.useEffect(() => {
3074
+ if (open) setViewYear(cursor.getFullYear());
3075
+ }, [open, cursor]);
3076
+ return /* @__PURE__ */ jsxRuntime.jsxs(Popover__namespace.Root, { open, onOpenChange: setOpen, children: [
3077
+ /* @__PURE__ */ jsxRuntime.jsx(Popover__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
3078
+ "button",
3079
+ {
3080
+ type: "button",
3081
+ className: "group ml-1 inline-flex items-center gap-1.5 rounded-md px-1.5 py-0.5 text-lg font-semibold tracking-tight text-foreground transition-colors hover:bg-background focus:outline-none focus-visible:ring-2 focus-visible:ring-accent",
3082
+ children: [
3083
+ label,
3084
+ /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, "aria-hidden": "true", className: "h-4 w-4 text-foreground-muted transition-transform duration-150 group-data-[state=open]:rotate-180", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 9l6 6 6-6" }) })
3085
+ ]
3086
+ }
3087
+ ) }),
3088
+ /* @__PURE__ */ jsxRuntime.jsx(Popover__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsxs(
3089
+ Popover__namespace.Content,
3090
+ {
3091
+ align: "start",
3092
+ sideOffset: 8,
3093
+ className: [
3094
+ "z-[400] w-64 rounded-lg border border-border bg-surface p-3 shadow-lg",
3095
+ "data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
3096
+ "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95"
3097
+ ].join(" "),
3098
+ children: [
3099
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-2 flex items-center justify-between", children: [
3100
+ /* @__PURE__ */ jsxRuntime.jsx(IconButton, { size: "sm", type: "bordered", icon: /* @__PURE__ */ jsxRuntime.jsx(Chevron4, { dir: "left" }), title: "Previous year", onClick: () => setViewYear((y) => y - 1) }),
3101
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold tabular-nums text-foreground", children: viewYear }),
3102
+ /* @__PURE__ */ jsxRuntime.jsx(IconButton, { size: "sm", type: "bordered", icon: /* @__PURE__ */ jsxRuntime.jsx(Chevron4, { dir: "right" }), title: "Next year", onClick: () => setViewYear((y) => y + 1) })
3103
+ ] }),
3104
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-3 gap-1", children: MONTHS_SHORT.map((m, i) => {
3105
+ const current = i === cursor.getMonth() && viewYear === cursor.getFullYear();
3106
+ return /* @__PURE__ */ jsxRuntime.jsx(
3107
+ "button",
3108
+ {
3109
+ type: "button",
3110
+ onClick: () => {
3111
+ onPick(new Date(viewYear, i, 1));
3112
+ setOpen(false);
3113
+ },
3114
+ className: [
3115
+ "rounded-md px-2 py-1.5 text-sm transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-accent",
3116
+ current ? "bg-accent font-semibold text-accent-fg" : "text-foreground hover:bg-background"
3117
+ ].join(" "),
3118
+ children: m
3119
+ },
3120
+ m
3121
+ );
3122
+ }) })
3123
+ ]
3124
+ }
3125
+ ) })
3126
+ ] });
3127
+ }
3061
3128
  var MAX_CHIPS = 3;
3062
3129
  function MonthView({
3063
3130
  cursor,
@@ -3082,7 +3149,9 @@ function MonthView({
3082
3149
  className: [
3083
3150
  "group flex min-h-[5rem] flex-col gap-1 border-b border-r border-border p-1.5 text-left transition-colors",
3084
3151
  "[&:nth-child(7n)]:border-r-0 focus:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-accent",
3085
- inMonth ? "bg-surface hover:bg-surface-raised" : "bg-background/40"
3152
+ // surface===surface-raised in light mode, so hover lifts toward the
3153
+ // cool chart-mist background instead (a visible, on-brand tint).
3154
+ inMonth ? "bg-surface hover:bg-background" : "bg-background hover:bg-surface"
3086
3155
  ].join(" "),
3087
3156
  children: [
3088
3157
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -3139,6 +3208,8 @@ function WeekView({
3139
3208
  onSelectEvent
3140
3209
  }) {
3141
3210
  const days = React29.useMemo(() => getWeekDays(cursor, weekStartsOn), [cursor, weekStartsOn]);
3211
+ const labels = React29.useMemo(() => weekdayLabels(weekStartsOn), [weekStartsOn]);
3212
+ const dow = (d) => labels[(d.getDay() - weekStartsOn + 7) % 7];
3142
3213
  const [startHour, endHour] = dayHours;
3143
3214
  const hours = React29.useMemo(
3144
3215
  () => Array.from({ length: endHour - startHour }, (_, i) => startHour + i),
@@ -3150,7 +3221,7 @@ function WeekView({
3150
3221
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid border-b border-border", style: { gridTemplateColumns: `3.5rem repeat(7, 1fr)` }, children: [
3151
3222
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-r border-border" }),
3152
3223
  days.map((d) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-r border-border px-1 py-1.5 text-center last:border-r-0", children: [
3153
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[11px] font-medium uppercase tracking-wide text-foreground-muted", children: weekdayLabels(weekStartsOn)[(d.getDay() - weekStartsOn + 7) % 7] }),
3224
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[11px] font-medium uppercase tracking-wide text-foreground-muted", children: dow(d) }),
3154
3225
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: ["mx-auto mt-0.5 flex h-6 w-6 items-center justify-center rounded-full text-xs tabular-nums", isToday(d) ? "bg-accent font-semibold text-accent-fg" : "text-foreground"].join(" "), children: d.getDate() })
3155
3226
  ] }, d.getTime()))
3156
3227
  ] }),
@@ -3163,9 +3234,9 @@ function WeekView({
3163
3234
  "button",
3164
3235
  {
3165
3236
  type: "button",
3166
- "aria-label": `${weekdayLabels(weekStartsOn)[(day.getDay() - weekStartsOn + 7) % 7]} ${day.getDate()} ${hourLabel(h)}`,
3237
+ "aria-label": `${dow(day)} ${day.getDate()} ${hourLabel(h)}`,
3167
3238
  onClick: () => onSelectSlot?.(new Date(day.getFullYear(), day.getMonth(), day.getDate(), h)),
3168
- className: "absolute left-0 right-0 border-b border-border/60 hover:bg-surface-raised/60 focus:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-accent",
3239
+ className: "absolute left-0 right-0 border-b border-border hover:bg-background focus:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-accent",
3169
3240
  style: { top: i * hourHeight, height: hourHeight }
3170
3241
  },
3171
3242
  h
@@ -3184,11 +3255,16 @@ function WeekView({
3184
3255
  onSelectEvent?.(e);
3185
3256
  },
3186
3257
  title: `${e.title} \xB7 ${timeLabel(e.start)}\u2013${timeLabel(e.end)}`,
3187
- className: "absolute left-0.5 right-0.5 overflow-hidden rounded-md border-l-2 px-1.5 py-0.5 text-left text-[11px] leading-tight text-foreground shadow-sm focus:outline-none focus-visible:ring-2 focus-visible:ring-accent",
3188
- style: { top: Math.max(0, top), height, borderLeftColor: color, backgroundColor: `color-mix(in oklab, ${color} 16%, var(--color-surface))` },
3258
+ className: "absolute left-0.5 right-0.5 overflow-hidden rounded-md border px-1.5 py-0.5 text-left text-[11px] leading-tight text-foreground shadow-sm transition-shadow hover:shadow-md focus:outline-none focus-visible:ring-2 focus-visible:ring-accent",
3259
+ style: {
3260
+ top: Math.max(0, top),
3261
+ height,
3262
+ backgroundColor: `color-mix(in oklab, ${color} 14%, var(--color-surface))`,
3263
+ borderColor: `color-mix(in oklab, ${color} 40%, var(--color-surface))`
3264
+ },
3189
3265
  children: [
3190
3266
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "truncate font-medium", children: e.title }),
3191
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "truncate text-foreground-muted", children: timeLabel(e.start) })
3267
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "truncate", style: { color }, children: timeLabel(e.start) })
3192
3268
  ]
3193
3269
  },
3194
3270
  e.id
@@ -5690,48 +5766,45 @@ function Pagination({
5690
5766
  if (next) setPerPageKey(next.key);
5691
5767
  }
5692
5768
  }, [serverSide, options.perPage, picker]);
5693
- const navBtn = (icon, disabled, onClick) => /* @__PURE__ */ jsxRuntime.jsx(IconButton, { disabled, onClick, icon });
5694
- const chevronRight = /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "h-5 w-5", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M9 5l7 7-7 7" }) });
5695
- const doubleChevronRight = /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "h-5 w-5", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M13 5l7 7-7 7M5 5l7 7-7 7" }) });
5696
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2 items-center justify-end pt-2", children: [
5697
- navBtn(
5698
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "rotate-180 inline-flex", children: doubleChevronRight }),
5699
- activePage === 0,
5700
- () => onPageChange(0)
5701
- ),
5702
- navBtn(
5703
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "rotate-180 inline-flex", children: chevronRight }),
5704
- activePage === 0,
5705
- () => activePage > 0 && onPageChange(activePage - 1)
5706
- ),
5707
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "bg-surface-raised rounded-lg ml-2 mr-2 shadow-sm p-2 w-10 text-center select-none text-foreground", children: activePage + 1 }),
5708
- navBtn(
5709
- chevronRight,
5710
- activePage === maxPage,
5711
- () => activePage < maxPage && onPageChange(activePage + 1)
5712
- ),
5713
- navBtn(
5714
- doubleChevronRight,
5715
- activePage === maxPage,
5716
- () => onPageChange(maxPage)
5717
- ),
5718
- options.withPicker && /* @__PURE__ */ jsxRuntime.jsx(
5719
- Dropdown,
5720
- {
5721
- style: { width: 80, position: "relative", bottom: 4 },
5722
- hasSearch: false,
5723
- items: picker,
5724
- isMultiselect: false,
5725
- value: displayPerPageKey,
5726
- onChange: ({ target: { value } }) => {
5727
- if (Array.isArray(value)) return;
5728
- const numKey = typeof value === "number" ? value : Number(value);
5729
- if (!serverSide) setPerPageKey(numKey);
5730
- const opt = picker.find((o) => o.key === numKey);
5731
- onPerPageChange(opt?.label ?? opt?.value ?? numKey);
5769
+ const navBtn = (icon, disabled, onClick, title) => /* @__PURE__ */ jsxRuntime.jsx(IconButton, { type: "bordered", size: "sm", disabled, onClick, icon, title });
5770
+ const chevronRight = /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "h-4 w-4", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M9 5l7 7-7 7" }) });
5771
+ const doubleChevronRight = /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "h-4 w-4", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M13 5l7 7-7 7M5 5l7 7-7 7" }) });
5772
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center justify-end gap-x-4 gap-y-3 pt-3", children: [
5773
+ options.withPicker && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mr-auto flex items-center gap-2", children: [
5774
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "whitespace-nowrap text-xs text-foreground-muted", children: "Rows per page" }),
5775
+ /* @__PURE__ */ jsxRuntime.jsx(
5776
+ Dropdown,
5777
+ {
5778
+ size: "sm",
5779
+ style: { width: 76 },
5780
+ hasSearch: false,
5781
+ items: picker,
5782
+ isMultiselect: false,
5783
+ value: displayPerPageKey,
5784
+ onChange: ({ target: { value } }) => {
5785
+ if (Array.isArray(value)) return;
5786
+ const numKey = typeof value === "number" ? value : Number(value);
5787
+ if (!serverSide) setPerPageKey(numKey);
5788
+ const opt = picker.find((o) => o.key === numKey);
5789
+ onPerPageChange(opt?.label ?? opt?.value ?? numKey);
5790
+ }
5732
5791
  }
5733
- }
5734
- )
5792
+ )
5793
+ ] }),
5794
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
5795
+ navBtn(/* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex rotate-180", children: doubleChevronRight }), activePage === 0, () => onPageChange(0), "First page"),
5796
+ navBtn(/* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex rotate-180", children: chevronRight }), activePage === 0, () => activePage > 0 && onPageChange(activePage - 1), "Previous page"),
5797
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "px-2 text-sm tabular-nums text-foreground-secondary select-none", children: [
5798
+ activePage + 1,
5799
+ " ",
5800
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-foreground-muted", children: [
5801
+ "/ ",
5802
+ maxPage + 1
5803
+ ] })
5804
+ ] }),
5805
+ navBtn(chevronRight, activePage === maxPage, () => activePage < maxPage && onPageChange(activePage + 1), "Next page"),
5806
+ navBtn(doubleChevronRight, activePage === maxPage, () => onPageChange(maxPage), "Last page")
5807
+ ] })
5735
5808
  ] });
5736
5809
  }
5737
5810
  function Table({
@@ -8459,7 +8532,7 @@ function OtpInput({
8459
8532
  emit(valid.join(""));
8460
8533
  focusBox(valid.length);
8461
8534
  };
8462
- return /* @__PURE__ */ jsxRuntime.jsx(Field, { className, label, htmlFor, errorId, errorMessage, required, layout, helperText, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", role: "group", "aria-label": typeof label === "string" ? label : "One-time code", children: chars.map((char, idx) => /* @__PURE__ */ jsxRuntime.jsxs(React29__default.default.Fragment, { children: [
8535
+ return /* @__PURE__ */ jsxRuntime.jsx(Field, { className, label, htmlFor, errorId, errorMessage, required, layout, helperText, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap items-center gap-2", role: "group", "aria-label": typeof label === "string" ? label : "One-time code", children: chars.map((char, idx) => /* @__PURE__ */ jsxRuntime.jsxs(React29__default.default.Fragment, { children: [
8463
8536
  /* @__PURE__ */ jsxRuntime.jsx(
8464
8537
  "input",
8465
8538
  {
@@ -8870,9 +8943,9 @@ function DateRangePicker({
8870
8943
  {
8871
8944
  align: "start",
8872
8945
  sideOffset: 4,
8873
- className: "bg-surface text-foreground border border-border rounded-lg shadow-md z-50 p-3 flex gap-3 animate-in fade-in-0 zoom-in-95",
8946
+ className: "bg-surface text-foreground border border-border rounded-lg shadow-md z-50 p-3 flex flex-col gap-3 sm:flex-row max-w-[calc(100vw-1rem)] max-h-[calc(100vh-2rem)] overflow-auto animate-in fade-in-0 zoom-in-95",
8874
8947
  children: [
8875
- presets && presets.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-1 pr-3 border-r border-border min-w-[120px]", children: presets.map((p) => /* @__PURE__ */ jsxRuntime.jsx(
8948
+ presets && presets.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-1 min-w-[120px] sm:pr-3 sm:border-r sm:border-border", children: presets.map((p) => /* @__PURE__ */ jsxRuntime.jsx(
8876
8949
  "button",
8877
8950
  {
8878
8951
  type: "button",
@@ -8885,7 +8958,7 @@ function DateRangePicker({
8885
8958
  },
8886
8959
  p.label
8887
8960
  )) }),
8888
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-4", children: [
8961
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4 sm:flex-row", children: [
8889
8962
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
8890
8963
  /* @__PURE__ */ jsxRuntime.jsx(
8891
8964
  "button",