sellmate-design-system-react 9.0.0-beta.2 → 9.0.0-beta.3

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.js CHANGED
@@ -12128,12 +12128,244 @@ function SCalendar({
12128
12128
  }
12129
12129
  );
12130
12130
  }
12131
+ var DATEPICKER_MODE_LIST_HEIGHT = 240;
12132
+ var DATEPICKER_MODE_ITEM_HEIGHT = 28;
12133
+ var YEAR_LIST_EDGE_BUFFER = 24;
12134
+ var YEAR_LIST_EXPAND_SIZE = 80;
12135
+ var MONTHS = Array.from({ length: 12 }, (_, i) => i + 1);
12136
+ var getTodayParts = () => {
12137
+ const today = /* @__PURE__ */ new Date();
12138
+ return {
12139
+ year: today.getFullYear(),
12140
+ month: today.getMonth() + 1
12141
+ };
12142
+ };
12143
+ var parseYear = (value) => {
12144
+ const year = Number(value?.slice(0, 4));
12145
+ return Number.isFinite(year) && year > 0 ? year : void 0;
12146
+ };
12147
+ var parseMonth = (value) => {
12148
+ const month = Number(value?.slice(5, 7));
12149
+ return Number.isFinite(month) && month >= 1 && month <= 12 ? month : void 0;
12150
+ };
12151
+ var formatMonthValue = (year, month) => `${year}-${String(month).padStart(2, "0")}`;
12152
+ var isYearDisabled = (year, selectable) => {
12153
+ if (!selectable) return false;
12154
+ const [start, end] = selectable;
12155
+ if (start !== "" && year < Number(start.slice(0, 4))) return true;
12156
+ if (end !== "" && year > Number(end.slice(0, 4))) return true;
12157
+ return false;
12158
+ };
12159
+ var isMonthDisabled = (year, month, selectable) => {
12160
+ if (!selectable) return false;
12161
+ const value = formatMonthValue(year, month);
12162
+ const [start, end] = selectable;
12163
+ if (start !== "" && value < start.slice(0, 7)) return true;
12164
+ if (end !== "" && value > end.slice(0, 7)) return true;
12165
+ return false;
12166
+ };
12167
+ function YearWheel({ value, anchorYear, selectable, onCommit }) {
12168
+ const listRef = useRef(null);
12169
+ const syncingScrollRef = useRef(false);
12170
+ const anchorYearRef = useRef(anchorYear);
12171
+ const [range, setRange] = useState(() => ({
12172
+ start: anchorYear - YEAR_LIST_EXPAND_SIZE,
12173
+ end: anchorYear + YEAR_LIST_EXPAND_SIZE
12174
+ }));
12175
+ const rangeStartRef = useRef(range.start);
12176
+ rangeStartRef.current = range.start;
12177
+ const years = Array.from({ length: range.end - range.start + 1 }, (_, i) => range.start + i);
12178
+ useLayoutEffect(() => {
12179
+ const list = listRef.current;
12180
+ if (!list) return;
12181
+ const index = anchorYearRef.current - rangeStartRef.current;
12182
+ syncingScrollRef.current = true;
12183
+ list.scrollTop = index * DATEPICKER_MODE_ITEM_HEIGHT;
12184
+ requestAnimationFrame(() => {
12185
+ syncingScrollRef.current = false;
12186
+ });
12187
+ }, []);
12188
+ const handleScroll = () => {
12189
+ const list = listRef.current;
12190
+ if (!list) return;
12191
+ if (syncingScrollRef.current) return;
12192
+ if (list.scrollTop < DATEPICKER_MODE_ITEM_HEIGHT * YEAR_LIST_EDGE_BUFFER) {
12193
+ const previousHeight = list.scrollHeight;
12194
+ setRange((current) => ({
12195
+ start: current.start - YEAR_LIST_EXPAND_SIZE,
12196
+ end: current.end
12197
+ }));
12198
+ requestAnimationFrame(() => {
12199
+ if (!listRef.current) return;
12200
+ syncingScrollRef.current = true;
12201
+ listRef.current.scrollTop += listRef.current.scrollHeight - previousHeight;
12202
+ requestAnimationFrame(() => {
12203
+ syncingScrollRef.current = false;
12204
+ });
12205
+ });
12206
+ return;
12207
+ }
12208
+ if (list.scrollHeight - list.scrollTop - list.clientHeight < DATEPICKER_MODE_ITEM_HEIGHT * YEAR_LIST_EDGE_BUFFER) {
12209
+ setRange((current) => ({
12210
+ start: current.start,
12211
+ end: current.end + YEAR_LIST_EXPAND_SIZE
12212
+ }));
12213
+ }
12214
+ };
12215
+ return /* @__PURE__ */ jsx("div", { className: "h-full w-full overflow-hidden bg-[var(--cmp-datepicker-mode-bg)]", children: /* @__PURE__ */ jsx(
12216
+ "div",
12217
+ {
12218
+ ref: listRef,
12219
+ role: "listbox",
12220
+ "aria-label": "year",
12221
+ className: "h-full overflow-y-auto overscroll-contain [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",
12222
+ style: {
12223
+ paddingTop: `calc((${DATEPICKER_MODE_LIST_HEIGHT}px - ${DATEPICKER_MODE_ITEM_HEIGHT}px) / 2)`,
12224
+ paddingBottom: `calc((${DATEPICKER_MODE_LIST_HEIGHT}px - ${DATEPICKER_MODE_ITEM_HEIGHT}px) / 2)`
12225
+ },
12226
+ onScroll: handleScroll,
12227
+ children: years.map((year) => {
12228
+ const selected = year === value;
12229
+ const disabled = isYearDisabled(year, selectable);
12230
+ return /* @__PURE__ */ jsx(
12231
+ "button",
12232
+ {
12233
+ type: "button",
12234
+ role: "option",
12235
+ "aria-selected": selected,
12236
+ disabled,
12237
+ className: cn(
12238
+ "flex w-full items-center justify-center gap-[var(--cmp-datepicker-mode-item-gap)] border-0 px-[var(--cmp-datepicker-mode-item-paddingX)] py-[var(--cmp-datepicker-mode-item-paddingY)] text-center font-base text-12 leading-[20px]",
12239
+ disabled && "cursor-not-allowed bg-[var(--cmp-datepicker-mode-item-bg-default)] font-medium text-[color:var(--cmp-datepicker-mode-item-content-disabled)]",
12240
+ !disabled && !selected && "cursor-pointer bg-[var(--cmp-datepicker-mode-item-bg-default)] font-medium text-[color:var(--cmp-datepicker-mode-item-content-default)] hover:bg-[var(--cmp-datepicker-mode-item-bg-hover)] hover:text-[color:var(--cmp-datepicker-mode-item-content-hover)]",
12241
+ !disabled && selected && "cursor-pointer bg-[var(--cmp-datepicker-mode-item-bg-default)] font-bold text-[color:var(--cmp-datepicker-mode-item-content-selected)]"
12242
+ ),
12243
+ onClick: () => !disabled && onCommit(year),
12244
+ children: year
12245
+ },
12246
+ year
12247
+ );
12248
+ })
12249
+ }
12250
+ ) });
12251
+ }
12252
+ function MonthWheel({ year, value, selectable, onCommit }) {
12253
+ const listRef = useRef(null);
12254
+ const initialValueRef = useRef(value);
12255
+ useLayoutEffect(() => {
12256
+ const list = listRef.current;
12257
+ if (!list) return;
12258
+ list.scrollTop = Math.max(
12259
+ 0,
12260
+ (initialValueRef.current - 1) * DATEPICKER_MODE_ITEM_HEIGHT - (list.clientHeight - DATEPICKER_MODE_ITEM_HEIGHT) / 2
12261
+ );
12262
+ }, []);
12263
+ return /* @__PURE__ */ jsx("div", { className: "h-full w-full overflow-hidden bg-[var(--cmp-datepicker-mode-bg)]", children: /* @__PURE__ */ jsx(
12264
+ "div",
12265
+ {
12266
+ ref: listRef,
12267
+ role: "listbox",
12268
+ "aria-label": "month",
12269
+ className: "h-full overflow-y-auto overscroll-contain [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",
12270
+ children: MONTHS.map((month) => {
12271
+ const selected = month === value;
12272
+ const disabled = isMonthDisabled(year, month, selectable);
12273
+ return /* @__PURE__ */ jsxs(
12274
+ "button",
12275
+ {
12276
+ type: "button",
12277
+ role: "option",
12278
+ "aria-selected": selected,
12279
+ disabled,
12280
+ className: cn(
12281
+ "flex w-full items-center justify-center gap-[var(--cmp-datepicker-mode-item-gap)] border-0 px-[var(--cmp-datepicker-mode-item-paddingX)] py-[var(--cmp-datepicker-mode-item-paddingY)] text-center font-base text-12 leading-[20px]",
12282
+ disabled && "cursor-not-allowed bg-[var(--cmp-datepicker-mode-item-bg-default)] font-medium text-[color:var(--cmp-datepicker-mode-item-content-disabled)]",
12283
+ !disabled && !selected && "cursor-pointer bg-[var(--cmp-datepicker-mode-item-bg-default)] font-medium text-[color:var(--cmp-datepicker-mode-item-content-default)] hover:bg-[var(--cmp-datepicker-mode-item-bg-hover)] hover:text-[color:var(--cmp-datepicker-mode-item-content-hover)]",
12284
+ !disabled && selected && "cursor-pointer bg-[var(--cmp-datepicker-mode-item-bg-default)] font-bold text-[color:var(--cmp-datepicker-mode-item-content-selected)]"
12285
+ ),
12286
+ onClick: () => !disabled && onCommit(month),
12287
+ children: [
12288
+ month,
12289
+ "\uC6D4"
12290
+ ]
12291
+ },
12292
+ month
12293
+ );
12294
+ })
12295
+ }
12296
+ ) });
12297
+ }
12298
+ function DatePickerListbox({
12299
+ mode,
12300
+ value,
12301
+ selectable,
12302
+ onValueChange,
12303
+ onClose
12304
+ }) {
12305
+ const today = getTodayParts();
12306
+ const [year, setYear] = useState(() => parseYear(value) ?? today.year);
12307
+ const [month, setMonth] = useState(() => parseMonth(value) ?? today.month);
12308
+ const commitYear = (nextYear) => {
12309
+ setYear(nextYear);
12310
+ if (mode === "year") {
12311
+ onValueChange?.(String(nextYear));
12312
+ onClose();
12313
+ return;
12314
+ }
12315
+ onValueChange?.(formatMonthValue(nextYear, month));
12316
+ };
12317
+ const commitMonth = (nextMonth) => {
12318
+ setMonth(nextMonth);
12319
+ onValueChange?.(formatMonthValue(year, nextMonth));
12320
+ onClose();
12321
+ };
12322
+ return /* @__PURE__ */ jsxs(
12323
+ "div",
12324
+ {
12325
+ className: cn(
12326
+ "inline-flex h-[240px] overflow-hidden rounded-[var(--cmp-datepicker-mode-radius)] bg-[var(--cmp-datepicker-mode-bg)] shadow-normal-sm",
12327
+ mode === "month" ? "gap-[var(--cmp-datepicker-mode-yearMonth-gap)]" : "w-[var(--cmp-datepicker-mode-year-width)]"
12328
+ ),
12329
+ children: [
12330
+ /* @__PURE__ */ jsx(
12331
+ "div",
12332
+ {
12333
+ className: cn(
12334
+ "min-w-0",
12335
+ mode === "month" ? "w-[var(--cmp-datepicker-mode-yearMonth-column-width)]" : "w-full"
12336
+ ),
12337
+ children: /* @__PURE__ */ jsx(
12338
+ YearWheel,
12339
+ {
12340
+ value: year,
12341
+ anchorYear: today.year,
12342
+ selectable,
12343
+ onCommit: commitYear
12344
+ }
12345
+ )
12346
+ }
12347
+ ),
12348
+ mode === "month" && /* @__PURE__ */ jsxs(Fragment, { children: [
12349
+ /* @__PURE__ */ jsx(
12350
+ "div",
12351
+ {
12352
+ "aria-hidden": true,
12353
+ className: "w-[var(--border-width-1)] self-stretch bg-[var(--sys-color-divider-default)]"
12354
+ }
12355
+ ),
12356
+ /* @__PURE__ */ jsx("div", { className: "min-w-0 w-[var(--cmp-datepicker-mode-yearMonth-column-width)]", children: /* @__PURE__ */ jsx(MonthWheel, { year, value: month, selectable, onCommit: commitMonth }) })
12357
+ ] })
12358
+ ]
12359
+ }
12360
+ );
12361
+ }
12131
12362
  function SDatePicker({
12132
12363
  value,
12133
12364
  onValueChange,
12134
12365
  onViewChange,
12366
+ mode = "date",
12135
12367
  size = "sm",
12136
- placeholder = "YYYY-MM-DD",
12368
+ placeholder,
12137
12369
  selectable,
12138
12370
  disabled = false,
12139
12371
  width,
@@ -12159,6 +12391,7 @@ function SDatePicker({
12159
12391
  const [focused, setFocused] = useState(false);
12160
12392
  const [ruleError, setRuleError] = useState("");
12161
12393
  const hasValue = value != null && value !== "";
12394
+ const resolvedPlaceholder = placeholder ?? (mode === "year" ? "YYYY" : mode === "month" ? "YYYY-MM" : "YYYY-MM-DD");
12162
12395
  useFormField({
12163
12396
  name,
12164
12397
  validate: () => {
@@ -12170,12 +12403,34 @@ function SDatePicker({
12170
12403
  });
12171
12404
  const resolvedError = error || ruleError !== "";
12172
12405
  const resolvedStatus = status ?? (rules && rules.length > 0 ? ruleError !== "" ? "error" : void 0 : void 0);
12173
- const dims = size === "md" ? { padX: 16, gap: 12, icon: 20, minW: 104, fontSize: 14, lineHeight: 24, radius: 6 } : { padX: 12, gap: 8, icon: 16, minW: 80, fontSize: 12, lineHeight: 20, radius: 4 };
12406
+ const dims = size === "md" ? {
12407
+ padX: 16,
12408
+ gap: 12,
12409
+ icon: 20,
12410
+ minW: 104,
12411
+ fieldMinW: 168,
12412
+ fontSize: 14,
12413
+ lineHeight: 24,
12414
+ radius: 6
12415
+ } : {
12416
+ padX: 12,
12417
+ gap: 8,
12418
+ icon: 16,
12419
+ minW: 80,
12420
+ fieldMinW: 128,
12421
+ fontSize: 12,
12422
+ lineHeight: 20,
12423
+ radius: 4
12424
+ };
12174
12425
  const select = (date) => {
12175
12426
  onValueChange?.(date);
12176
12427
  if (rules && rules.length > 0) setRuleError(runRules(date, rules));
12177
12428
  setOpen(false);
12178
12429
  };
12430
+ const selectListboxValue = (nextValue) => {
12431
+ onValueChange?.(nextValue);
12432
+ if (rules && rules.length > 0) setRuleError(runRules(nextValue, rules));
12433
+ };
12179
12434
  return /* @__PURE__ */ jsx(
12180
12435
  SField,
12181
12436
  {
@@ -12194,6 +12449,7 @@ function SDatePicker({
12194
12449
  focused: focused || open,
12195
12450
  errorMessage: ruleError !== "" ? ruleError : errorMessage,
12196
12451
  width,
12452
+ minWidth: dims.fieldMinW,
12197
12453
  disabled,
12198
12454
  className,
12199
12455
  style,
@@ -12228,7 +12484,7 @@ function SDatePicker({
12228
12484
  lineHeight: `${dims.lineHeight}px`,
12229
12485
  color: disabled ? "var(--cmp-datepicker-text-disabled)" : hasValue ? "var(--cmp-datepicker-text-default)" : "var(--cmp-field-hint-color)"
12230
12486
  },
12231
- children: hasValue ? value : placeholder
12487
+ children: hasValue ? value : resolvedPlaceholder
12232
12488
  }
12233
12489
  )
12234
12490
  ]
@@ -12244,7 +12500,7 @@ function SDatePicker({
12244
12500
  "z-50 max-w-[var(--radix-popover-content-available-width)]",
12245
12501
  FLOATING_SLIDE_ANIM
12246
12502
  ),
12247
- children: /* @__PURE__ */ jsx(
12503
+ children: mode === "date" ? /* @__PURE__ */ jsx(
12248
12504
  SCalendar,
12249
12505
  {
12250
12506
  value: value ?? void 0,
@@ -12253,6 +12509,15 @@ function SDatePicker({
12253
12509
  onValueChange: select,
12254
12510
  onViewChange
12255
12511
  }
12512
+ ) : /* @__PURE__ */ jsx(
12513
+ DatePickerListbox,
12514
+ {
12515
+ mode,
12516
+ value,
12517
+ selectable,
12518
+ onValueChange: selectListboxValue,
12519
+ onClose: () => setOpen(false)
12520
+ }
12256
12521
  )
12257
12522
  }
12258
12523
  ) })