@canvas-components/react-components 0.3.20 → 0.3.22

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
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  var React = require('react');
4
- var icons = require('@canvas-components/icons');
5
4
  var jsxRuntime = require('react/jsx-runtime');
5
+ var icons = require('@canvas-components/icons');
6
6
  var ReactDOM = require('react-dom');
7
7
 
8
8
  function _interopNamespace(e) {
@@ -50,6 +50,139 @@ function styleInject(css, { insertAt } = {}) {
50
50
 
51
51
  // src/styles/variables.css
52
52
  styleInject(":root {\n --canvas-react-color-primary: #1677ff;\n --canvas-react-color-primary-hover: #4096ff;\n --canvas-react-color-border: #d9d9d9;\n --canvas-react-color-border-strong: #bfbfbf;\n --canvas-react-color-text: #1f2937;\n --canvas-react-color-text-muted: #6b7280;\n --canvas-react-color-bg: #ffffff;\n --canvas-react-color-bg-soft: #f5f5f5;\n --canvas-react-color-bg-hover: #f3f4f6;\n --canvas-react-color-bg-active: #e6f4ff;\n --canvas-react-shadow-focus: 0 0 0 2px rgba(22, 119, 255, 0.12);\n --canvas-react-shadow-popup: 0 8px 24px rgba(15, 23, 42, 0.16);\n --canvas-react-radius-sm: 6px;\n --canvas-react-radius-md: 8px;\n --canvas-react-control-height: 32px;\n --canvas-react-font-size: 14px;\n --canvas-react-font-size-secondary: 12px;\n --canvas-react-font-size-label: 13px;\n --canvas-react-control-padding-inline: 11px;\n --canvas-react-control-padding-block: 0px;\n --canvas-react-content-zoom: 1;\n}\n.canvas-react-scrollbar {\n scrollbar-width: thin;\n}\n.canvas-react-scrollbar::-webkit-scrollbar {\n width: 8px;\n height: 8px;\n}\n.canvas-react-scrollbar::-webkit-scrollbar-track {\n background: transparent;\n}\n.canvas-react-scrollbar::-webkit-scrollbar-thumb {\n min-height: 32px;\n border: 2px solid transparent;\n border-radius: 999px;\n background: #aeb4bd;\n background-clip: content-box;\n}\n.canvas-react-scrollbar::-webkit-scrollbar-thumb:hover {\n background: #8f98a5;\n background-clip: content-box;\n}\n.canvas-react-scrollbar::-webkit-scrollbar-corner {\n background: transparent;\n}\n");
53
+ var ConfigContext = React.createContext({});
54
+ var variables = {
55
+ fontSize: "font-size",
56
+ secondaryFontSize: "font-size-secondary",
57
+ labelFontSize: "font-size-label",
58
+ colorText: "color-text",
59
+ colorTextSecondary: "color-text-muted",
60
+ colorPrimary: "color-primary",
61
+ colorPrimaryHover: "color-primary-hover",
62
+ colorBorder: "color-border",
63
+ colorBackground: "color-bg",
64
+ controlHeight: "control-height",
65
+ borderRadius: "radius-sm"
66
+ };
67
+ function reactConfigThemeStyle(theme) {
68
+ const style = {};
69
+ for (const key of Object.keys(variables)) {
70
+ const value = theme[key];
71
+ if (typeof value === "number" && Number.isFinite(value) && value >= 0)
72
+ style[`--canvas-react-${variables[key]}`] = `${value}px`;
73
+ else if (typeof value === "string" && value.trim())
74
+ style[`--canvas-react-${variables[key]}`] = value;
75
+ }
76
+ return style;
77
+ }
78
+ function useReactConfig() {
79
+ return React.useContext(ConfigContext);
80
+ }
81
+ function useReactConfigStyle() {
82
+ return reactConfigThemeStyle(useReactConfig());
83
+ }
84
+ function ReactConfigProvider({
85
+ theme = {},
86
+ style,
87
+ className,
88
+ children,
89
+ ...rest
90
+ }) {
91
+ const parent = useReactConfig();
92
+ const merged = React.useMemo(
93
+ () => ({
94
+ ...parent,
95
+ ...Object.fromEntries(
96
+ Object.entries(theme).filter(([, value]) => value !== void 0)
97
+ )
98
+ }),
99
+ [parent, theme]
100
+ );
101
+ return /* @__PURE__ */ jsxRuntime.jsx(ConfigContext.Provider, { value: merged, children: /* @__PURE__ */ jsxRuntime.jsx(
102
+ "div",
103
+ {
104
+ ...rest,
105
+ className: ["canvas-react-config-provider", className].filter(Boolean).join(" "),
106
+ style: {
107
+ color: "var(--canvas-react-color-text)",
108
+ fontSize: "var(--canvas-react-font-size)",
109
+ ...reactConfigThemeStyle(merged),
110
+ ...style
111
+ },
112
+ children
113
+ }
114
+ ) });
115
+ }
116
+ function ReactProgress({
117
+ percent,
118
+ label,
119
+ showInfo = true,
120
+ status = "normal",
121
+ className,
122
+ style
123
+ }) {
124
+ const configStyle = useReactConfigStyle();
125
+ const value = Number.isFinite(percent) ? Math.min(100, Math.max(0, percent)) : 0;
126
+ return /* @__PURE__ */ jsxRuntime.jsxs(
127
+ "div",
128
+ {
129
+ className: ["canvas-react-progress", className].filter(Boolean).join(" "),
130
+ role: "progressbar",
131
+ "aria-label": label,
132
+ "aria-valuemin": 0,
133
+ "aria-valuemax": 100,
134
+ "aria-valuenow": value,
135
+ style: {
136
+ ...configStyle,
137
+ display: "flex",
138
+ alignItems: "center",
139
+ gap: 12,
140
+ ...style
141
+ },
142
+ children: [
143
+ /* @__PURE__ */ jsxRuntime.jsx(
144
+ "div",
145
+ {
146
+ style: {
147
+ flex: 1,
148
+ height: 8,
149
+ overflow: "hidden",
150
+ borderRadius: 4,
151
+ background: "var(--canvas-react-color-bg-soft)"
152
+ },
153
+ children: /* @__PURE__ */ jsxRuntime.jsx(
154
+ "div",
155
+ {
156
+ style: {
157
+ width: `${value}%`,
158
+ height: "100%",
159
+ borderRadius: "inherit",
160
+ background: status === "exception" ? "#ff4d4f" : "var(--canvas-react-color-primary)",
161
+ transition: "width 160ms ease"
162
+ }
163
+ }
164
+ )
165
+ }
166
+ ),
167
+ showInfo && /* @__PURE__ */ jsxRuntime.jsxs(
168
+ "span",
169
+ {
170
+ style: {
171
+ minWidth: "4ch",
172
+ textAlign: "right",
173
+ color: "var(--canvas-react-color-text-muted)",
174
+ fontVariantNumeric: "tabular-nums"
175
+ },
176
+ children: [
177
+ Math.round(value),
178
+ "%"
179
+ ]
180
+ }
181
+ )
182
+ ]
183
+ }
184
+ );
185
+ }
53
186
  var REACT_ICON_DEFINITIONS = icons.iconDefinitions;
54
187
 
55
188
  // src/components/icon/style.css
@@ -1454,69 +1587,6 @@ var ReactInput = React.forwardRef(
1454
1587
  }
1455
1588
  }
1456
1589
  );
1457
- var ConfigContext = React.createContext({});
1458
- var variables = {
1459
- fontSize: "font-size",
1460
- secondaryFontSize: "font-size-secondary",
1461
- labelFontSize: "font-size-label",
1462
- colorText: "color-text",
1463
- colorTextSecondary: "color-text-muted",
1464
- colorPrimary: "color-primary",
1465
- colorPrimaryHover: "color-primary-hover",
1466
- colorBorder: "color-border",
1467
- colorBackground: "color-bg",
1468
- controlHeight: "control-height",
1469
- borderRadius: "radius-sm"
1470
- };
1471
- function reactConfigThemeStyle(theme) {
1472
- const style = {};
1473
- for (const key of Object.keys(variables)) {
1474
- const value = theme[key];
1475
- if (typeof value === "number" && Number.isFinite(value) && value >= 0)
1476
- style[`--canvas-react-${variables[key]}`] = `${value}px`;
1477
- else if (typeof value === "string" && value.trim())
1478
- style[`--canvas-react-${variables[key]}`] = value;
1479
- }
1480
- return style;
1481
- }
1482
- function useReactConfig() {
1483
- return React.useContext(ConfigContext);
1484
- }
1485
- function useReactConfigStyle() {
1486
- return reactConfigThemeStyle(useReactConfig());
1487
- }
1488
- function ReactConfigProvider({
1489
- theme = {},
1490
- style,
1491
- className,
1492
- children,
1493
- ...rest
1494
- }) {
1495
- const parent = useReactConfig();
1496
- const merged = React.useMemo(
1497
- () => ({
1498
- ...parent,
1499
- ...Object.fromEntries(
1500
- Object.entries(theme).filter(([, value]) => value !== void 0)
1501
- )
1502
- }),
1503
- [parent, theme]
1504
- );
1505
- return /* @__PURE__ */ jsxRuntime.jsx(ConfigContext.Provider, { value: merged, children: /* @__PURE__ */ jsxRuntime.jsx(
1506
- "div",
1507
- {
1508
- ...rest,
1509
- className: ["canvas-react-config-provider", className].filter(Boolean).join(" "),
1510
- style: {
1511
- color: "var(--canvas-react-color-text)",
1512
- fontSize: "var(--canvas-react-font-size)",
1513
- ...reactConfigThemeStyle(merged),
1514
- ...style
1515
- },
1516
- children
1517
- }
1518
- ) });
1519
- }
1520
1590
  var DEFAULT_CONTENT_SCALE = {
1521
1591
  scale: 1
1522
1592
  };
@@ -6311,89 +6381,300 @@ function compareDateTimeValue(left, right) {
6311
6381
  return left.localeCompare(right);
6312
6382
  }
6313
6383
 
6314
- // src/components/number-input/style.css
6315
- styleInject('@import "../../styles/variables.css";\n.canvas-react-number-input-affix-wrapper {\n box-sizing: border-box;\n display: inline-flex;\n align-items: center;\n width: 100%;\n min-width: 0;\n height: var(--canvas-react-control-height);\n border: 1px solid var(--canvas-react-color-border);\n border-radius: var(--canvas-react-radius-sm);\n background: var(--canvas-react-color-bg);\n color: var(--canvas-react-color-text);\n font-size: var(--canvas-react-font-size);\n outline: none;\n transition:\n border-color 0.2s ease,\n box-shadow 0.2s ease,\n background-color 0.2s ease;\n}\n.canvas-react-number-input-affix-wrapper:hover {\n border-color: var(--canvas-react-color-primary-hover);\n}\n.canvas-react-number-input-affix-wrapper:focus-within {\n border-color: var(--canvas-react-color-primary);\n box-shadow: var(--canvas-react-shadow-focus);\n}\n.canvas-react-number-input-affix-wrapper-disabled {\n background: #fafafa;\n color: #9ca3af;\n cursor: not-allowed;\n}\n.canvas-react-number-input {\n box-sizing: border-box;\n flex: 1 1 auto;\n width: 100%;\n min-width: 0;\n height: 100%;\n padding: var(--canvas-react-control-padding-block, 0px) var(--canvas-react-control-padding-inline, 11px);\n border: none;\n background: transparent;\n color: inherit;\n font-size: inherit;\n outline: none;\n appearance: textfield;\n -moz-appearance: textfield;\n}\n.canvas-react-number-input::placeholder {\n color: #9ca3af;\n}\n.canvas-react-number-input::-webkit-outer-spin-button,\n.canvas-react-number-input::-webkit-inner-spin-button {\n margin: 0;\n -webkit-appearance: none;\n}\n.canvas-react-number-input-suffix {\n display: inline-flex;\n align-items: center;\n padding-right: var(--canvas-react-control-padding-inline, 11px);\n}\n.canvas-react-number-input-clear {\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 12px;\n height: 12px;\n padding: 0;\n border: none;\n background: transparent;\n color: #9ca3af;\n opacity: 0;\n pointer-events: none;\n cursor: pointer;\n transition:\n color 0.2s ease,\n opacity 0.2s ease,\n transform 0.18s ease;\n}\n.canvas-react-number-input-affix-wrapper:hover .canvas-react-number-input-clear,\n.canvas-react-number-input-affix-wrapper:focus-within .canvas-react-number-input-clear {\n opacity: 1;\n pointer-events: auto;\n}\n.canvas-react-number-input-clear:hover {\n color: #6b7280;\n transform: rotate(90deg);\n}\n.canvas-react-number-input-clear-icon,\n.canvas-react-number-input-clear-icon::before {\n position: absolute;\n top: 50%;\n left: 50%;\n width: 8px;\n height: 1.25px;\n margin-top: -0.625px;\n margin-left: -4px;\n border-radius: 999px;\n background: currentColor;\n content: "";\n}\n.canvas-react-number-input-clear-icon {\n transform: rotate(45deg);\n}\n.canvas-react-number-input-clear-icon::before {\n transform: rotate(90deg);\n}\n');
6316
- var ReactNumberInput = React.forwardRef(
6317
- function ReactNumberInput2(props, ref) {
6384
+ // src/components/input-number/style.css
6385
+ styleInject('@import "../../styles/variables.css";\n.canvas-react-input-number {\n box-sizing: border-box;\n display: inline-flex;\n align-items: stretch;\n width: 100%;\n min-width: 0;\n height: var(--canvas-react-control-height);\n border: 1px solid var(--canvas-react-color-border);\n border-radius: var(--canvas-react-radius-sm);\n background: var(--canvas-react-color-bg);\n color: var(--canvas-react-color-text);\n font-size: var(--canvas-react-font-size);\n text-align: left;\n overflow: hidden;\n transition:\n border-color 0.2s ease,\n box-shadow 0.2s ease,\n background-color 0.2s ease;\n}\n.canvas-react-input-number:hover {\n border-color: var(--canvas-react-color-primary-hover);\n}\n.canvas-react-input-number-focused {\n border-color: var(--canvas-react-color-primary);\n box-shadow: var(--canvas-react-shadow-focus);\n}\n.canvas-react-input-number-disabled {\n background: #fafafa;\n color: #9ca3af;\n cursor: not-allowed;\n}\n.canvas-react-input-number-handler {\n position: relative;\n display: flex;\n flex: 0 0 28px;\n align-items: center;\n justify-content: center;\n margin: 0;\n padding: 0;\n border: none;\n background: transparent;\n color: var(--canvas-react-color-text-muted);\n cursor: pointer;\n transition: color 0.16s ease, background-color 0.16s ease;\n}\n.canvas-react-input-number-handler-down {\n border-right: 1px solid var(--canvas-react-color-border);\n}\n.canvas-react-input-number-handler-up {\n border-left: 1px solid var(--canvas-react-color-border);\n}\n.canvas-react-input-number-handler:hover:not(:disabled) {\n color: var(--canvas-react-color-primary);\n background: rgba(22, 119, 255, 0.06);\n}\n.canvas-react-input-number-handler:disabled {\n color: #c4c7cf;\n cursor: not-allowed;\n}\n.canvas-react-input-number-handler-icon {\n position: relative;\n display: block;\n width: 10px;\n height: 10px;\n}\n.canvas-react-input-number-handler-icon::before,\n.canvas-react-input-number-handler-icon::after {\n content: "";\n position: absolute;\n top: 50%;\n left: 50%;\n background: currentColor;\n border-radius: 1px;\n transform: translate(-50%, -50%);\n}\n.canvas-react-input-number-handler-icon::before {\n width: 10px;\n height: 1.5px;\n}\n.canvas-react-input-number-handler-up .canvas-react-input-number-handler-icon::after {\n width: 1.5px;\n height: 10px;\n}\n.canvas-react-input-number-input-wrap {\n display: flex;\n flex: 1 1 auto;\n align-items: center;\n min-width: 0;\n height: 100%;\n}\n.canvas-react-input-number-input {\n box-sizing: border-box;\n width: 100%;\n min-width: 0;\n height: 100%;\n padding: 0 var(--canvas-react-control-padding-inline, 8px);\n border: none;\n background: transparent;\n color: inherit;\n font-size: inherit;\n outline: none;\n text-align: inherit;\n appearance: textfield;\n -moz-appearance: textfield;\n}\n.canvas-react-input-number-input::placeholder {\n color: #9ca3af;\n}\n.canvas-react-input-number-input::-webkit-outer-spin-button,\n.canvas-react-input-number-input::-webkit-inner-spin-button {\n margin: 0;\n -webkit-appearance: none;\n}\n.canvas-react-input-number-addon {\n flex: 0 0 auto;\n padding-right: 8px;\n color: var(--canvas-react-color-text-muted);\n font-size: 12px;\n line-height: 1;\n user-select: none;\n}\n');
6386
+ var ReactInputNumber = React.forwardRef(
6387
+ function ReactInputNumber2(props, ref) {
6318
6388
  const {
6389
+ addonAfter,
6319
6390
  className,
6320
6391
  changeOnWheel = false,
6392
+ controls = false,
6393
+ defaultValue = null,
6321
6394
  disabled,
6395
+ formatter,
6396
+ initialText,
6397
+ max,
6398
+ min,
6322
6399
  onBlur,
6323
6400
  onChange,
6401
+ onCommit,
6402
+ onFocus,
6324
6403
  onKeyDown,
6325
- onWheel,
6326
6404
  onPressEnter,
6405
+ onWheel,
6406
+ parser,
6407
+ precision,
6408
+ step = 1,
6327
6409
  style,
6328
6410
  value,
6329
6411
  ...restProps
6330
6412
  } = props;
6331
- const [inputValue, setInputValue] = React.useState(toDisplayValue(value));
6413
+ const isControlled = value !== void 0;
6414
+ const [innerValue, setInnerValue] = React.useState(
6415
+ isControlled ? value ?? null : defaultValue
6416
+ );
6417
+ const currentValue = isControlled ? value ?? null : innerValue;
6418
+ const [draftText, setDraftText] = React.useState(
6419
+ initialText ?? formatDisplayValue(
6420
+ currentValue,
6421
+ formatter,
6422
+ resolvePrecision(precision, props.step, currentValue)
6423
+ )
6424
+ );
6425
+ const initialTextPendingRef = React.useRef(initialText !== void 0);
6426
+ const initialValueRef = React.useRef(currentValue);
6427
+ const [focused, setFocused] = React.useState(false);
6428
+ const resolvedPrecision = React.useMemo(
6429
+ () => resolvePrecision(precision, props.step, currentValue),
6430
+ [precision, props.step, currentValue]
6431
+ );
6332
6432
  React.useEffect(() => {
6333
- setInputValue(toDisplayValue(value));
6334
- }, [value]);
6335
- return /* @__PURE__ */ jsxRuntime.jsx(
6433
+ if (initialValueRef.current !== currentValue) {
6434
+ initialTextPendingRef.current = false;
6435
+ }
6436
+ initialValueRef.current = currentValue;
6437
+ if (!focused && !initialTextPendingRef.current) {
6438
+ setDraftText(
6439
+ formatDisplayValue(currentValue, formatter, resolvedPrecision)
6440
+ );
6441
+ }
6442
+ }, [currentValue, focused, formatter, resolvedPrecision]);
6443
+ const commitValue = (nextValue, stepPrecision) => {
6444
+ initialTextPendingRef.current = false;
6445
+ const normalized = normalizeNumberValue(nextValue, {
6446
+ min,
6447
+ max,
6448
+ precision: stepPrecision ?? resolvePrecision(precision, props.step, nextValue)
6449
+ });
6450
+ if (!isControlled) {
6451
+ setInnerValue(normalized);
6452
+ }
6453
+ if (normalized !== currentValue) {
6454
+ onChange?.(normalized);
6455
+ }
6456
+ onCommit?.(normalized);
6457
+ setDraftText(
6458
+ formatDisplayValue(
6459
+ normalized,
6460
+ formatter,
6461
+ resolvePrecision(precision, props.step, normalized)
6462
+ )
6463
+ );
6464
+ return normalized;
6465
+ };
6466
+ const stepBy = (direction) => {
6467
+ if (disabled) {
6468
+ return;
6469
+ }
6470
+ const base = currentValue == null || !Number.isFinite(currentValue) ? 0 : currentValue;
6471
+ const next = base + direction * step;
6472
+ commitValue(next, resolvedPrecision);
6473
+ };
6474
+ const atMin = currentValue != null && min != null && currentValue <= min + Number.EPSILON;
6475
+ const atMax = currentValue != null && max != null && currentValue >= max - Number.EPSILON;
6476
+ return /* @__PURE__ */ jsxRuntime.jsxs(
6336
6477
  "span",
6337
6478
  {
6338
6479
  className: joinClassNames(
6339
- `${REACT_COMPONENT_PREFIX}-number-input-affix-wrapper`,
6340
- disabled && `${REACT_COMPONENT_PREFIX}-number-input-affix-wrapper-disabled`
6480
+ `${REACT_COMPONENT_PREFIX}-input-number`,
6481
+ focused && `${REACT_COMPONENT_PREFIX}-input-number-focused`,
6482
+ disabled && `${REACT_COMPONENT_PREFIX}-input-number-disabled`,
6483
+ className
6341
6484
  ),
6342
6485
  style,
6343
- children: /* @__PURE__ */ jsxRuntime.jsx(
6344
- "input",
6345
- {
6346
- ...restProps,
6347
- ref,
6348
- disabled,
6349
- type: "number",
6350
- value: inputValue,
6351
- className: joinClassNames(
6352
- `${REACT_COMPONENT_PREFIX}-number-input`,
6353
- className
6354
- ),
6355
- onChange: (event) => {
6356
- const nextText = event.target.value;
6357
- setInputValue(nextText);
6358
- onChange?.(parseNumberValue(nextText));
6359
- },
6360
- onBlur: (event) => {
6361
- setInputValue(toDisplayValue(parseNumberValue(event.target.value)));
6362
- onBlur?.(event);
6363
- },
6364
- onKeyDown: (event) => {
6365
- onKeyDown?.(event);
6366
- if (event.key === "Enter") {
6367
- onPressEnter?.(event);
6368
- }
6369
- },
6370
- onWheel: (event) => {
6371
- if (!changeOnWheel) event.currentTarget.blur();
6372
- onWheel?.(event);
6373
- }
6374
- }
6375
- )
6376
- }
6377
- );
6378
- }
6379
- );
6380
- function parseNumberValue(value) {
6381
- if (value.trim().length === 0) {
6382
- return null;
6383
- }
6384
- const nextValue = Number(value);
6385
- return Number.isFinite(nextValue) ? nextValue : null;
6386
- }
6387
- function toDisplayValue(value) {
6388
- return value == null ? "" : String(value);
6389
- }
6486
+ children: [
6487
+ controls && /* @__PURE__ */ jsxRuntime.jsx(
6488
+ "button",
6489
+ {
6490
+ type: "button",
6491
+ tabIndex: -1,
6492
+ disabled: disabled || atMin,
6493
+ className: joinClassNames(
6494
+ `${REACT_COMPONENT_PREFIX}-input-number-handler`,
6495
+ `${REACT_COMPONENT_PREFIX}-input-number-handler-down`
6496
+ ),
6497
+ "aria-label": "\u51CF\u5C11",
6498
+ onMouseDown: (event) => {
6499
+ event.preventDefault();
6500
+ },
6501
+ onClick: () => {
6502
+ stepBy(-1);
6503
+ },
6504
+ children: /* @__PURE__ */ jsxRuntime.jsx(
6505
+ "span",
6506
+ {
6507
+ className: `${REACT_COMPONENT_PREFIX}-input-number-handler-icon`,
6508
+ "aria-hidden": "true"
6509
+ }
6510
+ )
6511
+ }
6512
+ ),
6513
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `${REACT_COMPONENT_PREFIX}-input-number-input-wrap`, children: [
6514
+ /* @__PURE__ */ jsxRuntime.jsx(
6515
+ "input",
6516
+ {
6517
+ ...restProps,
6518
+ type: "text",
6519
+ ref,
6520
+ disabled,
6521
+ inputMode: "decimal",
6522
+ min,
6523
+ max,
6524
+ step,
6525
+ value: draftText,
6526
+ className: `${REACT_COMPONENT_PREFIX}-input-number-input`,
6527
+ onFocus: (event) => {
6528
+ setFocused(true);
6529
+ onFocus?.(event);
6530
+ },
6531
+ onChange: (event) => {
6532
+ const nextText = event.target.value;
6533
+ if (!isValidNumberDraftText(nextText)) {
6534
+ return;
6535
+ }
6536
+ setDraftText(nextText);
6537
+ if (isIncompleteNumberText(nextText)) {
6538
+ return;
6539
+ }
6540
+ const parsed = parser ? parser(nextText) : parseNumberText(nextText);
6541
+ if (!isControlled) {
6542
+ setInnerValue(parsed);
6543
+ }
6544
+ onChange?.(parsed);
6545
+ },
6546
+ onBlur: (event) => {
6547
+ setFocused(false);
6548
+ const parsed = parser ? parser(event.target.value) : parseNumberText(event.target.value);
6549
+ commitValue(parsed);
6550
+ onBlur?.(event);
6551
+ },
6552
+ onKeyDown: (event) => {
6553
+ onKeyDown?.(event);
6554
+ if (event.defaultPrevented) return;
6555
+ if (event.key === "ArrowUp") {
6556
+ event.preventDefault();
6557
+ stepBy(1);
6558
+ } else if (event.key === "ArrowDown") {
6559
+ event.preventDefault();
6560
+ stepBy(-1);
6561
+ } else if (event.key === "Enter") {
6562
+ const parsed = parser ? parser(event.currentTarget.value) : parseNumberText(event.currentTarget.value);
6563
+ commitValue(parsed);
6564
+ onPressEnter?.(event);
6565
+ }
6566
+ },
6567
+ onWheel: (event) => {
6568
+ if (changeOnWheel && !disabled && event.deltaY !== 0) {
6569
+ stepBy(event.deltaY < 0 ? 1 : -1);
6570
+ } else if (!changeOnWheel) {
6571
+ event.currentTarget.blur();
6572
+ }
6573
+ onWheel?.(event);
6574
+ }
6575
+ }
6576
+ ),
6577
+ addonAfter != null ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${REACT_COMPONENT_PREFIX}-input-number-addon`, children: addonAfter }) : null
6578
+ ] }),
6579
+ controls && /* @__PURE__ */ jsxRuntime.jsx(
6580
+ "button",
6581
+ {
6582
+ type: "button",
6583
+ tabIndex: -1,
6584
+ disabled: disabled || atMax,
6585
+ className: joinClassNames(
6586
+ `${REACT_COMPONENT_PREFIX}-input-number-handler`,
6587
+ `${REACT_COMPONENT_PREFIX}-input-number-handler-up`
6588
+ ),
6589
+ "aria-label": "\u589E\u52A0",
6590
+ onMouseDown: (event) => {
6591
+ event.preventDefault();
6592
+ },
6593
+ onClick: () => {
6594
+ stepBy(1);
6595
+ },
6596
+ children: /* @__PURE__ */ jsxRuntime.jsx(
6597
+ "span",
6598
+ {
6599
+ className: `${REACT_COMPONENT_PREFIX}-input-number-handler-icon`,
6600
+ "aria-hidden": "true"
6601
+ }
6602
+ )
6603
+ }
6604
+ )
6605
+ ]
6606
+ }
6607
+ );
6608
+ }
6609
+ );
6610
+ function parseNumberText(value) {
6611
+ const text = value.trim().replace(/%/g, "");
6612
+ if (!text) {
6613
+ return null;
6614
+ }
6615
+ const nextValue = Number(text);
6616
+ return Number.isFinite(nextValue) ? nextValue : null;
6617
+ }
6618
+ function isValidNumberDraftText(value) {
6619
+ const minusIndex = value.indexOf("-");
6620
+ return (minusIndex === -1 || minusIndex === 0 && value.lastIndexOf("-") === 0) && value.indexOf(".") === value.lastIndexOf(".");
6621
+ }
6622
+ function isIncompleteNumberText(value) {
6623
+ const text = value.trim();
6624
+ return text === "-" || text === "." || text === "-." || /^-?\d+\.$/.test(text);
6625
+ }
6626
+ function resolvePrecision(precision, step, value) {
6627
+ if (typeof precision === "number" && Number.isInteger(precision) && precision >= 0) {
6628
+ return precision;
6629
+ }
6630
+ if (step == null) {
6631
+ return void 0;
6632
+ }
6633
+ return Math.max(countDecimalPlaces(step), countDecimalPlaces(value));
6634
+ }
6635
+ function countDecimalPlaces(value) {
6636
+ if (value == null || !Number.isFinite(value)) return 0;
6637
+ const [mantissa, exponentText] = String(value).toLowerCase().split("e");
6638
+ const fractionDigits = mantissa.split(".")[1]?.length ?? 0;
6639
+ return Math.min(100, Math.max(0, fractionDigits - Number(exponentText ?? 0)));
6640
+ }
6641
+ function normalizeNumberValue(value, options) {
6642
+ if (value == null || !Number.isFinite(value)) {
6643
+ return null;
6644
+ }
6645
+ let next = value;
6646
+ if (options.min != null) {
6647
+ next = Math.max(options.min, next);
6648
+ }
6649
+ if (options.max != null) {
6650
+ next = Math.min(options.max, next);
6651
+ }
6652
+ if (options.precision == null) {
6653
+ return next;
6654
+ }
6655
+ const factor = 10 ** options.precision;
6656
+ return Math.round(next * factor) / factor;
6657
+ }
6658
+ function formatDisplayValue(value, formatter, precision) {
6659
+ if (formatter) {
6660
+ return formatter(value);
6661
+ }
6662
+ if (value == null || !Number.isFinite(value)) {
6663
+ return "";
6664
+ }
6665
+ if (precision == null) {
6666
+ return String(value);
6667
+ }
6668
+ return precision > 0 ? value.toFixed(precision) : String(Math.round(value));
6669
+ }
6390
6670
 
6391
6671
  // src/components/input-range/style.css
6392
- styleInject('@import "../../styles/variables.css";\n.canvas-react-input-range {\n box-sizing: border-box;\n display: inline-flex;\n align-items: center;\n width: 100%;\n min-width: 0;\n height: var(--canvas-react-control-height);\n overflow: hidden;\n border: 1px solid var(--canvas-react-color-border);\n border-radius: var(--canvas-react-radius-sm);\n background: var(--canvas-react-color-bg);\n color: var(--canvas-react-color-text);\n font-size: var(--canvas-react-font-size);\n outline: none;\n transition:\n border-color 0.2s ease,\n box-shadow 0.2s ease,\n background-color 0.2s ease;\n}\n.canvas-react-input-range:hover {\n border-color: var(--canvas-react-color-primary-hover);\n}\n.canvas-react-input-range:focus-within {\n border-color: var(--canvas-react-color-primary);\n box-shadow: var(--canvas-react-shadow-focus);\n}\n.canvas-react-input-range-disabled {\n background: #fafafa;\n color: #9ca3af;\n cursor: not-allowed;\n}\n.canvas-react-input-range > .canvas-react-number-input-affix-wrapper,\n.canvas-react-input-range > .canvas-react-number-input-affix-wrapper:hover,\n.canvas-react-input-range > .canvas-react-number-input-affix-wrapper:focus-within {\n flex: 1 1 0;\n width: 0;\n height: 100%;\n border: 0;\n border-radius: 0;\n box-shadow: none;\n}\n.canvas-react-input-range-separator {\n flex: 0 0 auto;\n color: #9ca3af;\n line-height: 1;\n}\n');
6672
+ styleInject('@import "../../styles/variables.css";\n.canvas-react-input-range {\n box-sizing: border-box;\n display: inline-flex;\n align-items: center;\n width: 100%;\n min-width: 0;\n height: var(--canvas-react-control-height);\n overflow: hidden;\n border: 1px solid var(--canvas-react-color-border);\n border-radius: var(--canvas-react-radius-sm);\n background: var(--canvas-react-color-bg);\n color: var(--canvas-react-color-text);\n font-size: var(--canvas-react-font-size);\n outline: none;\n transition:\n border-color 0.2s ease,\n box-shadow 0.2s ease,\n background-color 0.2s ease;\n}\n.canvas-react-input-range:hover {\n border-color: var(--canvas-react-color-primary-hover);\n}\n.canvas-react-input-range:focus-within {\n border-color: var(--canvas-react-color-primary);\n box-shadow: var(--canvas-react-shadow-focus);\n}\n.canvas-react-input-range-disabled {\n background: #fafafa;\n color: #9ca3af;\n cursor: not-allowed;\n}\n.canvas-react-input-range > .canvas-react-input-number,\n.canvas-react-input-range > .canvas-react-input-number:hover,\n.canvas-react-input-range > .canvas-react-input-number:focus-within {\n flex: 1 1 0;\n width: 0;\n height: 100%;\n border: 0;\n border-radius: 0;\n box-shadow: none;\n}\n.canvas-react-input-range-separator {\n flex: 0 0 auto;\n color: #9ca3af;\n line-height: 1;\n}\n');
6393
6673
  var ReactInputRange = React.forwardRef(function ReactInputRange2(props, ref) {
6394
6674
  const {
6395
6675
  autoFocus,
6396
6676
  className,
6677
+ changeOnWheel,
6397
6678
  disabled,
6398
6679
  max,
6399
6680
  min,
@@ -6436,7 +6717,7 @@ var ReactInputRange = React.forwardRef(function ReactInputRange2(props, ref) {
6436
6717
  style,
6437
6718
  children: [
6438
6719
  /* @__PURE__ */ jsxRuntime.jsx(
6439
- ReactNumberInput,
6720
+ ReactInputNumber,
6440
6721
  {
6441
6722
  ...restProps,
6442
6723
  ref: startInputRef,
@@ -6450,12 +6731,13 @@ var ReactInputRange = React.forwardRef(function ReactInputRange2(props, ref) {
6450
6731
  onFocus,
6451
6732
  onBlur: handleBlur,
6452
6733
  onKeyDown,
6453
- onPressEnter
6734
+ onPressEnter,
6735
+ changeOnWheel
6454
6736
  }
6455
6737
  ),
6456
6738
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${REACT_COMPONENT_PREFIX}-input-range-separator`, children: rangeSeparator }),
6457
6739
  /* @__PURE__ */ jsxRuntime.jsx(
6458
- ReactNumberInput,
6740
+ ReactInputNumber,
6459
6741
  {
6460
6742
  ...restProps,
6461
6743
  value: value[1],
@@ -6468,7 +6750,8 @@ var ReactInputRange = React.forwardRef(function ReactInputRange2(props, ref) {
6468
6750
  onFocus,
6469
6751
  onBlur: handleBlur,
6470
6752
  onKeyDown,
6471
- onPressEnter
6753
+ onPressEnter,
6754
+ changeOnWheel
6472
6755
  }
6473
6756
  )
6474
6757
  ]
@@ -8179,12 +8462,6 @@ function ReactCol({ span = 24, style, ...props }) {
8179
8462
  }
8180
8463
  );
8181
8464
  }
8182
- function ReactTooltip({ title, children }) {
8183
- return React.cloneElement(children, {
8184
- title: typeof title === "string" ? title : void 0,
8185
- "aria-label": typeof title === "string" ? title : void 0
8186
- });
8187
- }
8188
8465
  var RadioGroupContext = React.createContext({});
8189
8466
  function ReactRadioOption({
8190
8467
  value,
@@ -8259,252 +8536,19 @@ function ReactTextArea({ className, ...props }) {
8259
8536
  );
8260
8537
  }
8261
8538
 
8262
- // src/components/input-number/style.css
8263
- styleInject('@import "../../styles/variables.css";\n.canvas-react-input-number {\n box-sizing: border-box;\n display: inline-flex;\n align-items: stretch;\n width: 100%;\n min-width: 0;\n height: var(--canvas-react-control-height);\n border: 1px solid var(--canvas-react-color-border);\n border-radius: var(--canvas-react-radius-sm);\n background: var(--canvas-react-color-bg);\n color: var(--canvas-react-color-text);\n font-size: var(--canvas-react-font-size);\n overflow: hidden;\n transition:\n border-color 0.2s ease,\n box-shadow 0.2s ease,\n background-color 0.2s ease;\n}\n.canvas-react-input-number:hover {\n border-color: var(--canvas-react-color-primary-hover);\n}\n.canvas-react-input-number-focused {\n border-color: var(--canvas-react-color-primary);\n box-shadow: var(--canvas-react-shadow-focus);\n}\n.canvas-react-input-number-disabled {\n background: #fafafa;\n color: #9ca3af;\n cursor: not-allowed;\n}\n.canvas-react-input-number-handler {\n position: relative;\n display: flex;\n flex: 0 0 28px;\n align-items: center;\n justify-content: center;\n margin: 0;\n padding: 0;\n border: none;\n background: transparent;\n color: var(--canvas-react-color-text-muted);\n cursor: pointer;\n transition: color 0.16s ease, background-color 0.16s ease;\n}\n.canvas-react-input-number-handler-down {\n border-right: 1px solid var(--canvas-react-color-border);\n}\n.canvas-react-input-number-handler-up {\n border-left: 1px solid var(--canvas-react-color-border);\n}\n.canvas-react-input-number-handler:hover:not(:disabled) {\n color: var(--canvas-react-color-primary);\n background: rgba(22, 119, 255, 0.06);\n}\n.canvas-react-input-number-handler:disabled {\n color: #c4c7cf;\n cursor: not-allowed;\n}\n.canvas-react-input-number-handler-icon {\n position: relative;\n display: block;\n width: 10px;\n height: 10px;\n}\n.canvas-react-input-number-handler-icon::before,\n.canvas-react-input-number-handler-icon::after {\n content: "";\n position: absolute;\n top: 50%;\n left: 50%;\n background: currentColor;\n border-radius: 1px;\n transform: translate(-50%, -50%);\n}\n.canvas-react-input-number-handler-icon::before {\n width: 10px;\n height: 1.5px;\n}\n.canvas-react-input-number-handler-up .canvas-react-input-number-handler-icon::after {\n width: 1.5px;\n height: 10px;\n}\n.canvas-react-input-number-input-wrap {\n display: flex;\n flex: 1 1 auto;\n align-items: center;\n min-width: 0;\n height: 100%;\n}\n.canvas-react-input-number-input {\n box-sizing: border-box;\n width: 100%;\n min-width: 0;\n height: 100%;\n padding: 0 8px;\n border: none;\n background: transparent;\n color: inherit;\n font-size: inherit;\n outline: none;\n text-align: center;\n appearance: textfield;\n -moz-appearance: textfield;\n}\n.canvas-react-input-number-input::placeholder {\n color: #9ca3af;\n}\n.canvas-react-input-number-input::-webkit-outer-spin-button,\n.canvas-react-input-number-input::-webkit-inner-spin-button {\n margin: 0;\n -webkit-appearance: none;\n}\n.canvas-react-input-number-addon {\n flex: 0 0 auto;\n padding-right: 8px;\n color: var(--canvas-react-color-text-muted);\n font-size: 12px;\n line-height: 1;\n user-select: none;\n}\n');
8264
- var ReactInputNumber = React.forwardRef(
8265
- function ReactInputNumber2(props, ref) {
8266
- const {
8267
- addonAfter,
8268
- className,
8269
- controls = false,
8270
- defaultValue = null,
8271
- disabled,
8272
- formatter,
8273
- max,
8274
- min,
8275
- onBlur,
8276
- onChange,
8277
- onCommit,
8278
- onFocus,
8279
- onKeyDown,
8280
- parser,
8281
- precision,
8282
- step = 1,
8283
- style,
8284
- value,
8285
- ...restProps
8286
- } = props;
8287
- const isControlled = value !== void 0;
8288
- const [innerValue, setInnerValue] = React.useState(
8289
- isControlled ? value ?? null : defaultValue
8290
- );
8291
- const currentValue = isControlled ? value ?? null : innerValue;
8292
- const [draftText, setDraftText] = React.useState(
8293
- formatDisplayValue(
8294
- currentValue,
8295
- formatter,
8296
- resolvePrecision(precision, step),
8297
- step
8298
- )
8299
- );
8300
- const [focused, setFocused] = React.useState(false);
8301
- const resolvedPrecision = React.useMemo(
8302
- () => resolvePrecision(precision, step),
8303
- [precision, step]
8304
- );
8305
- React.useEffect(() => {
8306
- if (!focused) {
8307
- setDraftText(
8308
- formatDisplayValue(currentValue, formatter, resolvedPrecision, step)
8309
- );
8310
- }
8311
- }, [currentValue, focused, formatter, resolvedPrecision, step]);
8312
- const commitValue = (nextValue) => {
8313
- const normalized = normalizeNumberValue(nextValue, {
8314
- min,
8315
- max,
8316
- precision: resolvedPrecision
8317
- });
8318
- if (!isControlled) {
8319
- setInnerValue(normalized);
8320
- }
8321
- onChange?.(normalized);
8322
- onCommit?.(normalized);
8323
- setDraftText(
8324
- formatDisplayValue(normalized, formatter, resolvedPrecision, step)
8325
- );
8326
- return normalized;
8327
- };
8328
- const stepBy = (direction) => {
8329
- if (disabled) {
8330
- return;
8331
- }
8332
- const base = currentValue == null || !Number.isFinite(currentValue) ? 0 : currentValue;
8333
- const next = base + direction * step;
8334
- commitValue(next);
8335
- };
8336
- const atMin = currentValue != null && min != null && currentValue <= min + Number.EPSILON;
8337
- const atMax = currentValue != null && max != null && currentValue >= max - Number.EPSILON;
8338
- return /* @__PURE__ */ jsxRuntime.jsxs(
8339
- "span",
8340
- {
8341
- className: joinClassNames(
8342
- `${REACT_COMPONENT_PREFIX}-input-number`,
8343
- focused && `${REACT_COMPONENT_PREFIX}-input-number-focused`,
8344
- disabled && `${REACT_COMPONENT_PREFIX}-input-number-disabled`,
8345
- className
8346
- ),
8347
- style,
8348
- children: [
8349
- controls && /* @__PURE__ */ jsxRuntime.jsx(
8350
- "button",
8351
- {
8352
- type: "button",
8353
- tabIndex: -1,
8354
- disabled: disabled || atMin,
8355
- className: joinClassNames(
8356
- `${REACT_COMPONENT_PREFIX}-input-number-handler`,
8357
- `${REACT_COMPONENT_PREFIX}-input-number-handler-down`
8358
- ),
8359
- "aria-label": "\u51CF\u5C11",
8360
- onMouseDown: (event) => {
8361
- event.preventDefault();
8362
- },
8363
- onClick: () => {
8364
- stepBy(-1);
8365
- },
8366
- children: /* @__PURE__ */ jsxRuntime.jsx(
8367
- "span",
8368
- {
8369
- className: `${REACT_COMPONENT_PREFIX}-input-number-handler-icon`,
8370
- "aria-hidden": "true"
8371
- }
8372
- )
8373
- }
8374
- ),
8375
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `${REACT_COMPONENT_PREFIX}-input-number-input-wrap`, children: [
8376
- /* @__PURE__ */ jsxRuntime.jsx(
8377
- "input",
8378
- {
8379
- ...restProps,
8380
- ref,
8381
- disabled,
8382
- inputMode: "decimal",
8383
- value: draftText,
8384
- className: `${REACT_COMPONENT_PREFIX}-input-number-input`,
8385
- onFocus: (event) => {
8386
- setFocused(true);
8387
- onFocus?.(event);
8388
- },
8389
- onChange: (event) => {
8390
- const nextText = event.target.value;
8391
- setDraftText(nextText);
8392
- const parsed = parser ? parser(nextText) : parseNumberText(nextText);
8393
- if (!isControlled) {
8394
- setInnerValue(parsed);
8395
- }
8396
- onChange?.(parsed);
8397
- },
8398
- onBlur: (event) => {
8399
- setFocused(false);
8400
- const parsed = parser ? parser(event.target.value) : parseNumberText(event.target.value);
8401
- commitValue(parsed);
8402
- onBlur?.(event);
8403
- },
8404
- onKeyDown: (event) => {
8405
- if (event.key === "ArrowUp") {
8406
- event.preventDefault();
8407
- stepBy(1);
8408
- } else if (event.key === "ArrowDown") {
8409
- event.preventDefault();
8410
- stepBy(-1);
8411
- } else if (event.key === "Enter") {
8412
- const parsed = parser ? parser(event.currentTarget.value) : parseNumberText(event.currentTarget.value);
8413
- commitValue(parsed);
8414
- }
8415
- onKeyDown?.(event);
8416
- }
8417
- }
8418
- ),
8419
- addonAfter != null ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${REACT_COMPONENT_PREFIX}-input-number-addon`, children: addonAfter }) : null
8420
- ] }),
8421
- controls && /* @__PURE__ */ jsxRuntime.jsx(
8422
- "button",
8423
- {
8424
- type: "button",
8425
- tabIndex: -1,
8426
- disabled: disabled || atMax,
8427
- className: joinClassNames(
8428
- `${REACT_COMPONENT_PREFIX}-input-number-handler`,
8429
- `${REACT_COMPONENT_PREFIX}-input-number-handler-up`
8430
- ),
8431
- "aria-label": "\u589E\u52A0",
8432
- onMouseDown: (event) => {
8433
- event.preventDefault();
8434
- },
8435
- onClick: () => {
8436
- stepBy(1);
8437
- },
8438
- children: /* @__PURE__ */ jsxRuntime.jsx(
8439
- "span",
8440
- {
8441
- className: `${REACT_COMPONENT_PREFIX}-input-number-handler-icon`,
8442
- "aria-hidden": "true"
8443
- }
8444
- )
8445
- }
8446
- )
8447
- ]
8448
- }
8449
- );
8450
- }
8451
- );
8452
- function parseNumberText(value) {
8453
- const text = value.trim().replace(/%/g, "");
8454
- if (!text) {
8455
- return null;
8456
- }
8457
- const nextValue = Number(text);
8458
- return Number.isFinite(nextValue) ? nextValue : null;
8459
- }
8460
- function resolvePrecision(precision, step) {
8461
- if (typeof precision === "number" && Number.isInteger(precision) && precision >= 0) {
8462
- return precision;
8463
- }
8464
- const stepText = String(step);
8465
- if (!stepText.includes(".")) {
8466
- return 0;
8467
- }
8468
- return stepText.split(".")[1]?.length ?? 0;
8469
- }
8470
- function normalizeNumberValue(value, options) {
8471
- if (value == null || !Number.isFinite(value)) {
8472
- return null;
8473
- }
8474
- let next = value;
8475
- if (options.min != null) {
8476
- next = Math.max(options.min, next);
8477
- }
8478
- if (options.max != null) {
8479
- next = Math.min(options.max, next);
8480
- }
8481
- const factor = 10 ** options.precision;
8482
- return Math.round(next * factor) / factor;
8483
- }
8484
- function formatDisplayValue(value, formatter, precision, step) {
8485
- if (formatter) {
8486
- return formatter(value);
8487
- }
8488
- if (value == null || !Number.isFinite(value)) {
8489
- return "";
8490
- }
8491
- const digits = resolvePrecision(precision, step);
8492
- return digits > 0 ? value.toFixed(digits) : String(Math.round(value));
8493
- }
8494
-
8495
- // src/shared/scrollbar-settings.ts
8496
- var STORAGE_KEY = "canvas-components:shared-scrollbar-settings";
8497
- var listeners = /* @__PURE__ */ new Set();
8498
- function readStoredSettings() {
8499
- try {
8500
- const raw = globalThis.localStorage?.getItem(STORAGE_KEY);
8501
- if (!raw) return { shared: false };
8502
- const parsed = JSON.parse(raw);
8503
- if (!parsed || typeof parsed !== "object") return { shared: false };
8504
- const settings = parsed;
8505
- return {
8506
- shared: settings.shared === true,
8507
- value: settings.value && typeof settings.value === "object" ? settings.value : void 0
8539
+ // src/shared/scrollbar-settings.ts
8540
+ var STORAGE_KEY = "canvas-components:shared-scrollbar-settings";
8541
+ var listeners = /* @__PURE__ */ new Set();
8542
+ function readStoredSettings() {
8543
+ try {
8544
+ const raw = globalThis.localStorage?.getItem(STORAGE_KEY);
8545
+ if (!raw) return { shared: false };
8546
+ const parsed = JSON.parse(raw);
8547
+ if (!parsed || typeof parsed !== "object") return { shared: false };
8548
+ const settings = parsed;
8549
+ return {
8550
+ shared: settings.shared === true,
8551
+ value: settings.value && typeof settings.value === "object" ? settings.value : void 0
8508
8552
  };
8509
8553
  } catch {
8510
8554
  return { shared: false };
@@ -9471,6 +9515,548 @@ function ReactDropdown(props) {
9471
9515
  )
9472
9516
  ] });
9473
9517
  }
9518
+ var VIEWPORT_MARGIN = 8;
9519
+ function clamp3(value, min, max) {
9520
+ return Math.max(min, Math.min(value, max));
9521
+ }
9522
+ function resolveTooltipLayout(params) {
9523
+ const {
9524
+ anchor,
9525
+ width,
9526
+ height,
9527
+ viewportWidth,
9528
+ viewportHeight,
9529
+ gap,
9530
+ arrowSize
9531
+ } = params;
9532
+ const centerX = anchor.x + anchor.width / 2;
9533
+ const centerY = anchor.y + anchor.height / 2;
9534
+ const right = anchor.x + anchor.width;
9535
+ const bottom = anchor.y + anchor.height;
9536
+ const room = {
9537
+ bottom: viewportHeight - VIEWPORT_MARGIN - bottom - gap,
9538
+ top: anchor.y - VIEWPORT_MARGIN - gap,
9539
+ right: viewportWidth - VIEWPORT_MARGIN - right - gap,
9540
+ left: anchor.x - VIEWPORT_MARGIN - gap
9541
+ };
9542
+ const choices = ["bottom", "top", "right", "left"];
9543
+ const placement = choices.find(
9544
+ (side) => room[side] >= (side === "bottom" || side === "top" ? height : width)
9545
+ ) ?? choices.reduce(
9546
+ (best, side) => room[side] - (side === "bottom" || side === "top" ? height : width) > room[best] - (best === "bottom" || best === "top" ? height : width) ? side : best
9547
+ );
9548
+ const rawLeft = placement === "right" ? right + gap : placement === "left" ? anchor.x - width - gap : centerX - width / 2;
9549
+ const rawTop = placement === "bottom" ? bottom + gap : placement === "top" ? anchor.y - height - gap : centerY - height / 2;
9550
+ const left = clamp3(
9551
+ rawLeft,
9552
+ VIEWPORT_MARGIN,
9553
+ Math.max(VIEWPORT_MARGIN, viewportWidth - width - VIEWPORT_MARGIN)
9554
+ );
9555
+ const top = clamp3(
9556
+ rawTop,
9557
+ VIEWPORT_MARGIN,
9558
+ Math.max(VIEWPORT_MARGIN, viewportHeight - height - VIEWPORT_MARGIN)
9559
+ );
9560
+ const horizontal = placement === "bottom" || placement === "top";
9561
+ const available = horizontal ? width : height;
9562
+ const target = horizontal ? centerX - left : centerY - top;
9563
+ const arrowOffset = clamp3(
9564
+ target - arrowSize / 2,
9565
+ 4,
9566
+ Math.max(4, available - arrowSize - 4)
9567
+ );
9568
+ return { left, top, placement, arrowOffset };
9569
+ }
9570
+ function ReactTooltip(props) {
9571
+ if ("request" in props) {
9572
+ return /* @__PURE__ */ jsxRuntime.jsx(ReactPositionedTooltip, { request: props.request });
9573
+ }
9574
+ return React.cloneElement(props.children, {
9575
+ title: typeof props.title === "string" ? props.title : void 0,
9576
+ "aria-label": typeof props.title === "string" ? props.title : void 0
9577
+ });
9578
+ }
9579
+ function ReactPositionedTooltip(props) {
9580
+ const { request } = props;
9581
+ const tooltipRef = React.useRef(null);
9582
+ const arrowRef = React.useRef(null);
9583
+ const zoom = typeof request?.contentZoom === "number" && Number.isFinite(request.contentZoom) && request.contentZoom > 0 ? request.contentZoom : 1;
9584
+ const arrowSize = 8 * zoom;
9585
+ React.useLayoutEffect(() => {
9586
+ const tooltip = tooltipRef.current;
9587
+ const arrow = arrowRef.current;
9588
+ if (!tooltip || !arrow || !request || typeof window === "undefined") return;
9589
+ const updateLayout = () => {
9590
+ const bounds = tooltip.getBoundingClientRect();
9591
+ const layout = resolveTooltipLayout({
9592
+ anchor: request.anchorRect ?? {
9593
+ x: request.x,
9594
+ y: request.y,
9595
+ width: 0,
9596
+ height: 0
9597
+ },
9598
+ width: bounds.width,
9599
+ height: bounds.height,
9600
+ viewportWidth: window.innerWidth,
9601
+ viewportHeight: window.innerHeight,
9602
+ gap: 6 * zoom,
9603
+ arrowSize
9604
+ });
9605
+ tooltip.style.left = `${layout.left}px`;
9606
+ tooltip.style.top = `${layout.top}px`;
9607
+ tooltip.dataset.placement = layout.placement;
9608
+ arrow.style.left = "";
9609
+ arrow.style.right = "";
9610
+ arrow.style.top = "";
9611
+ arrow.style.bottom = "";
9612
+ arrow.style.borderTop = "";
9613
+ arrow.style.borderRight = "";
9614
+ arrow.style.borderBottom = "";
9615
+ arrow.style.borderLeft = "";
9616
+ const arrowBorder = request.variant === "error" ? "1px solid rgba(255, 77, 79, 0.2)" : "none";
9617
+ if (layout.placement === "bottom" || layout.placement === "top") {
9618
+ arrow.style.left = `${layout.arrowOffset}px`;
9619
+ if (layout.placement === "bottom") {
9620
+ arrow.style.top = `${-arrowSize / 2}px`;
9621
+ arrow.style.borderTop = arrowBorder;
9622
+ arrow.style.borderLeft = arrowBorder;
9623
+ } else {
9624
+ arrow.style.bottom = `${-arrowSize / 2}px`;
9625
+ arrow.style.borderBottom = arrowBorder;
9626
+ arrow.style.borderRight = arrowBorder;
9627
+ }
9628
+ } else {
9629
+ arrow.style.top = `${layout.arrowOffset}px`;
9630
+ if (layout.placement === "right") {
9631
+ arrow.style.left = `${-arrowSize / 2}px`;
9632
+ arrow.style.borderLeft = arrowBorder;
9633
+ arrow.style.borderBottom = arrowBorder;
9634
+ } else {
9635
+ arrow.style.right = `${-arrowSize / 2}px`;
9636
+ arrow.style.borderTop = arrowBorder;
9637
+ arrow.style.borderRight = arrowBorder;
9638
+ }
9639
+ }
9640
+ };
9641
+ updateLayout();
9642
+ window.addEventListener("resize", updateLayout);
9643
+ return () => window.removeEventListener("resize", updateLayout);
9644
+ }, [request, arrowSize, zoom]);
9645
+ if (!request) return null;
9646
+ const fontSize = 14 * zoom;
9647
+ const paddingBlock = 6 * zoom;
9648
+ const paddingInline = 10 * zoom;
9649
+ const background = request.variant === "error" ? "#ffffff" : "rgba(17, 24, 39, 0.92)";
9650
+ const style = {
9651
+ position: "fixed",
9652
+ left: request.x,
9653
+ top: request.y,
9654
+ boxSizing: "border-box",
9655
+ maxWidth: request.variant === "resize" ? "calc(100vw - 16px)" : `min(${320 * zoom}px, calc(100vw - 16px))`,
9656
+ maxHeight: "calc(100vh - 16px)",
9657
+ padding: `${paddingBlock}px ${paddingInline}px`,
9658
+ borderRadius: 6 * zoom,
9659
+ background,
9660
+ color: request.variant === "error" ? "#ff4d4f" : "#fff",
9661
+ fontSize,
9662
+ lineHeight: 1.5,
9663
+ boxShadow: request.variant === "error" ? "0 10px 30px rgba(255, 77, 79, 0.16)" : "0 10px 30px rgba(15, 23, 42, 0.18)",
9664
+ border: request.variant === "error" ? "1px solid rgba(255, 77, 79, 0.2)" : "none",
9665
+ pointerEvents: "none",
9666
+ zIndex: 1200,
9667
+ whiteSpace: request.variant === "resize" ? "nowrap" : "pre-wrap",
9668
+ wordBreak: "break-word"
9669
+ };
9670
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: tooltipRef, role: "tooltip", style, children: [
9671
+ /* @__PURE__ */ jsxRuntime.jsx(
9672
+ "span",
9673
+ {
9674
+ style: {
9675
+ display: "block",
9676
+ maxHeight: `calc(100vh - ${16 + 2 * paddingBlock + 2}px)`,
9677
+ overflow: "hidden",
9678
+ textOverflow: request.variant === "resize" ? "ellipsis" : void 0
9679
+ },
9680
+ children: request.content
9681
+ }
9682
+ ),
9683
+ /* @__PURE__ */ jsxRuntime.jsx(
9684
+ "span",
9685
+ {
9686
+ ref: arrowRef,
9687
+ "aria-hidden": "true",
9688
+ style: {
9689
+ position: "absolute",
9690
+ width: arrowSize,
9691
+ height: arrowSize,
9692
+ boxSizing: "border-box",
9693
+ background,
9694
+ transform: "rotate(45deg)",
9695
+ pointerEvents: "none"
9696
+ }
9697
+ }
9698
+ )
9699
+ ] });
9700
+ }
9701
+
9702
+ // src/components/tour/style.css
9703
+ styleInject(".canvas-react-tour {\n position: fixed;\n inset: 0;\n z-index: 1800;\n pointer-events: none;\n font-family: inherit;\n}\n.canvas-react-tour-backdrop {\n position: absolute;\n inset: 0;\n background: rgba(15, 23, 42, 0.56);\n pointer-events: auto;\n}\n.canvas-react-tour-mask {\n position: absolute;\n inset: 0;\n pointer-events: none;\n}\n.canvas-react-tour-focus {\n position: absolute;\n border-radius: 8px;\n box-shadow: 0 0 0 2px #60a5fa, 0 0 0 5px rgba(96, 165, 250, 0.24);\n pointer-events: none;\n}\n.canvas-react-tour-focus-secondary {\n box-shadow: 0 0 0 3px #f59e0b, 0 0 0 7px rgba(245, 158, 11, 0.24);\n}\n.canvas-react-tour-card {\n position: absolute;\n box-sizing: border-box;\n width: min(360px, calc(100vw - 24px));\n max-height: calc(100vh - 24px);\n overflow: auto;\n padding: 16px;\n border: 1px solid #dbeafe;\n border-radius: 12px;\n background: #fff;\n color: #172033;\n box-shadow: 0 20px 50px rgba(15, 23, 42, 0.26);\n pointer-events: auto;\n transition: top 320ms cubic-bezier(0.22, 1, 0.36, 1), left 320ms cubic-bezier(0.22, 1, 0.36, 1);\n animation: canvas-react-tour-appear 220ms ease-out both;\n}\n.canvas-react-tour-card:focus {\n outline: none;\n}\n.canvas-react-tour-heading,\n.canvas-react-tour-actions {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.canvas-react-tour-heading {\n justify-content: space-between;\n color: #64748b;\n font-size: 12px;\n}\n.canvas-react-tour-heading button {\n border: 0;\n background: transparent;\n color: #64748b;\n font-size: 22px;\n cursor: pointer;\n}\n.canvas-react-tour-card h3 {\n margin: 8px 0;\n font-size: 16px;\n line-height: 1.4;\n}\n.canvas-react-tour-content {\n animation: canvas-react-tour-content-enter 260ms ease-out both;\n}\n.canvas-react-tour-description {\n font-size: 13px;\n line-height: 1.65;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n}\n.canvas-react-tour-progress {\n display: flex;\n gap: 4px;\n overflow-x: auto;\n padding: 16px 0;\n}\n.canvas-react-tour-progress button {\n flex: 0 0 16px;\n height: 5px;\n border: 0;\n border-radius: 5px;\n background: #cbd5e1;\n cursor: pointer;\n}\n.canvas-react-tour-progress button.active {\n background: #2563eb;\n}\n.canvas-react-tour-progress button {\n transition: background-color 220ms ease;\n}\n.canvas-react-tour-start-step {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-bottom: 12px;\n color: #475569;\n font-size: 12px;\n}\n.canvas-react-tour-start-step input {\n box-sizing: border-box;\n width: 56px;\n height: 28px;\n padding: 2px 6px;\n border: 1px solid #cbd5e1;\n border-radius: 6px;\n background: #fff;\n color: #172033;\n font: inherit;\n text-align: center;\n}\n.canvas-react-tour-start-step input:focus-visible {\n outline: 2px solid #60a5fa;\n outline-offset: 1px;\n}\n.canvas-react-tour-actions {\n justify-content: flex-end;\n}\n.canvas-react-tour-actions button {\n padding: 5px 10px;\n border: 1px solid #cbd5e1;\n border-radius: 6px;\n background: #fff;\n color: #334155;\n cursor: pointer;\n}\n.canvas-react-tour-actions button:last-child {\n background: #2563eb;\n border-color: #2563eb;\n color: #fff;\n}\n.canvas-react-tour-actions button:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n@keyframes canvas-react-tour-appear {\n from {\n opacity: 0;\n transform: translateY(8px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n@keyframes canvas-react-tour-content-enter {\n from {\n opacity: 0;\n transform: translateY(5px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n@media (prefers-reduced-motion: reduce) {\n .canvas-react-tour-card,\n .canvas-react-tour-content {\n animation: none;\n }\n .canvas-react-tour-card,\n .canvas-react-tour-progress button {\n transition: none;\n }\n}\n");
9704
+ function focusRect(rect, pad = 6) {
9705
+ if (!rect || rect.width <= 0 || rect.height <= 0) return null;
9706
+ const left = Math.max(0, rect.left - pad);
9707
+ const top = Math.max(0, rect.top - pad);
9708
+ const right = Math.min(window.innerWidth, rect.left + rect.width + pad);
9709
+ const bottom = Math.min(window.innerHeight, rect.top + rect.height + pad);
9710
+ if (right <= left || bottom <= top) return null;
9711
+ return { left, top, width: right - left, height: bottom - top };
9712
+ }
9713
+ function collapsedRect(rect) {
9714
+ return {
9715
+ left: rect.left + rect.width / 2,
9716
+ top: rect.top + rect.height / 2,
9717
+ width: 0,
9718
+ height: 0
9719
+ };
9720
+ }
9721
+ function interpolateRect(from, to, progress) {
9722
+ if (!from && !to) return null;
9723
+ const start = from ?? collapsedRect(to);
9724
+ const end = to ?? collapsedRect(from);
9725
+ return {
9726
+ left: start.left + (end.left - start.left) * progress,
9727
+ top: start.top + (end.top - start.top) * progress,
9728
+ width: start.width + (end.width - start.width) * progress,
9729
+ height: start.height + (end.height - start.height) * progress
9730
+ };
9731
+ }
9732
+ function ReactTour(props) {
9733
+ const {
9734
+ open,
9735
+ steps,
9736
+ current,
9737
+ onChange,
9738
+ onClose,
9739
+ interval = 3e3,
9740
+ playing = false,
9741
+ onPlayingChange
9742
+ } = props;
9743
+ const cardRef = React.useRef(null);
9744
+ const maskId = React.useRef(
9745
+ `canvas-react-tour-mask-${Math.random().toString(36).slice(2)}`
9746
+ );
9747
+ const [geometry, setGeometry] = React.useState(null);
9748
+ const [displayFocus, setDisplayFocus] = React.useState({
9749
+ primary: null,
9750
+ secondary: null
9751
+ });
9752
+ const displayFocusRef = React.useRef(displayFocus);
9753
+ const previousStepRef = React.useRef(null);
9754
+ const animationRef = React.useRef(null);
9755
+ const [startStep, setStartStep] = React.useState(String(current + 1));
9756
+ const step = steps[current];
9757
+ React.useEffect(() => {
9758
+ if (open)
9759
+ setStartStep(
9760
+ String(
9761
+ current === steps.length - 1 && steps.length > 1 ? 1 : current + 1
9762
+ )
9763
+ );
9764
+ }, [open, current, steps.length]);
9765
+ const playFromSelectedStep = () => {
9766
+ if (playing) {
9767
+ onPlayingChange?.(false);
9768
+ return;
9769
+ }
9770
+ const value = Number(startStep);
9771
+ if (!Number.isInteger(value) || !startStep.trim()) return;
9772
+ const index = Math.min(steps.length - 1, Math.max(0, value - 1));
9773
+ setStartStep(String(index + 1));
9774
+ if (index !== current) onChange(index);
9775
+ onPlayingChange?.(true);
9776
+ };
9777
+ React.useLayoutEffect(() => {
9778
+ if (!open || !step) return;
9779
+ let pending;
9780
+ const update = (reveal = false) => {
9781
+ const target = typeof step.target === "string" ? document.querySelector(step.target) : step.target?.();
9782
+ let parent = target instanceof HTMLElement ? target.parentElement : null;
9783
+ let opened = false;
9784
+ while (parent) {
9785
+ if (parent.hidden && parent.previousElementSibling instanceof HTMLButtonElement) {
9786
+ parent.previousElementSibling.click();
9787
+ opened = true;
9788
+ }
9789
+ parent = parent.parentElement;
9790
+ }
9791
+ if (opened) {
9792
+ if (pending !== void 0) window.clearTimeout(pending);
9793
+ pending = window.setTimeout(() => update(true), 0);
9794
+ return;
9795
+ }
9796
+ if (reveal && target instanceof HTMLElement)
9797
+ target.scrollIntoView?.({ block: "nearest", inline: "nearest" });
9798
+ setGeometry({
9799
+ stepIndex: current,
9800
+ primary: focusRect(
9801
+ target instanceof HTMLElement ? target.getBoundingClientRect() : target ?? null
9802
+ ),
9803
+ secondary: focusRect(props.highlightTarget?.() ?? null, 8)
9804
+ });
9805
+ };
9806
+ update(true);
9807
+ const refresh = () => update();
9808
+ window.addEventListener("resize", refresh);
9809
+ window.addEventListener("scroll", refresh, true);
9810
+ return () => {
9811
+ if (pending !== void 0) window.clearTimeout(pending);
9812
+ window.removeEventListener("resize", refresh);
9813
+ window.removeEventListener("scroll", refresh, true);
9814
+ };
9815
+ }, [open, step, current, props.highlightTarget]);
9816
+ React.useLayoutEffect(() => {
9817
+ if (animationRef.current !== null) {
9818
+ window.cancelAnimationFrame(animationRef.current);
9819
+ animationRef.current = null;
9820
+ }
9821
+ if (!open) {
9822
+ previousStepRef.current = null;
9823
+ displayFocusRef.current = { primary: null, secondary: null };
9824
+ setDisplayFocus(displayFocusRef.current);
9825
+ return;
9826
+ }
9827
+ if (!geometry || geometry.stepIndex !== current) return;
9828
+ const target = {
9829
+ primary: geometry.primary,
9830
+ secondary: geometry.secondary
9831
+ };
9832
+ const previousStep = previousStepRef.current;
9833
+ previousStepRef.current = current;
9834
+ if (previousStep === null || previousStep === current || window.matchMedia?.("(prefers-reduced-motion: reduce)").matches) {
9835
+ displayFocusRef.current = target;
9836
+ setDisplayFocus(target);
9837
+ return;
9838
+ }
9839
+ const start = displayFocusRef.current;
9840
+ let startedAt = null;
9841
+ const tick = (time) => {
9842
+ startedAt ?? (startedAt = time);
9843
+ const progress = Math.min(1, Math.max(0, (time - startedAt) / 320));
9844
+ const eased = 1 - Math.pow(1 - progress, 3);
9845
+ const next = {
9846
+ primary: interpolateRect(start.primary, target.primary, eased),
9847
+ secondary: interpolateRect(start.secondary, target.secondary, eased)
9848
+ };
9849
+ displayFocusRef.current = next;
9850
+ setDisplayFocus(next);
9851
+ if (progress < 1)
9852
+ animationRef.current = window.requestAnimationFrame(tick);
9853
+ else {
9854
+ animationRef.current = null;
9855
+ displayFocusRef.current = target;
9856
+ setDisplayFocus(target);
9857
+ }
9858
+ };
9859
+ animationRef.current = window.requestAnimationFrame(tick);
9860
+ return () => {
9861
+ if (animationRef.current !== null) {
9862
+ window.cancelAnimationFrame(animationRef.current);
9863
+ animationRef.current = null;
9864
+ }
9865
+ };
9866
+ }, [open, current, geometry]);
9867
+ React.useEffect(() => {
9868
+ if (!open || !playing || !step || steps.length < 2) return;
9869
+ const timer = window.setTimeout(
9870
+ () => {
9871
+ if (current >= steps.length - 1) onPlayingChange?.(false);
9872
+ else onChange(current + 1);
9873
+ },
9874
+ Math.max(500, interval)
9875
+ );
9876
+ return () => window.clearTimeout(timer);
9877
+ }, [
9878
+ open,
9879
+ playing,
9880
+ current,
9881
+ interval,
9882
+ steps.length,
9883
+ step,
9884
+ onChange,
9885
+ onPlayingChange
9886
+ ]);
9887
+ React.useEffect(() => {
9888
+ if (!open) return;
9889
+ const onKeyDown = (event) => {
9890
+ if (event.key === "Escape") onClose();
9891
+ if (event.key === "ArrowLeft" && current > 0) onChange(current - 1);
9892
+ if (event.key === "ArrowRight" && current < steps.length - 1)
9893
+ onChange(current + 1);
9894
+ };
9895
+ window.addEventListener("keydown", onKeyDown);
9896
+ return () => window.removeEventListener("keydown", onKeyDown);
9897
+ }, [open, current, steps.length, onChange, onClose]);
9898
+ React.useEffect(() => {
9899
+ if (open) cardRef.current?.focus();
9900
+ }, [open]);
9901
+ if (!open || !step || typeof document === "undefined") return null;
9902
+ const focus = displayFocus.primary;
9903
+ const secondaryFocus = displayFocus.secondary;
9904
+ const cardFocus = geometry?.stepIndex === current ? geometry.primary : focus;
9905
+ const holes = [focus, secondaryFocus].filter(
9906
+ (value) => value !== null && value.width > 0 && value.height > 0
9907
+ );
9908
+ const placeBelow = !cardFocus || cardFocus.top + cardFocus.height + 280 < window.innerHeight;
9909
+ const side = cardFocus && cardFocus.height > 180 ? cardFocus.left + cardFocus.width + 382 < window.innerWidth ? "right" : cardFocus.left > 382 ? "left" : null : null;
9910
+ const top = side && cardFocus ? Math.max(12, Math.min(cardFocus.top, window.innerHeight - 280)) : cardFocus ? placeBelow ? cardFocus.top + cardFocus.height + 12 : Math.max(12, cardFocus.top - 272) : Math.max(12, (window.innerHeight - 260) / 2);
9911
+ const left = side && cardFocus ? side === "right" ? cardFocus.left + cardFocus.width + 12 : cardFocus.left - 372 : cardFocus ? Math.max(12, Math.min(cardFocus.left, window.innerWidth - 382)) : Math.max(12, (window.innerWidth - 360) / 2);
9912
+ return ReactDOM.createPortal(
9913
+ /* @__PURE__ */ jsxRuntime.jsxs(
9914
+ "div",
9915
+ {
9916
+ className: `canvas-react-tour${props.className ? ` ${props.className}` : ""}`,
9917
+ children: [
9918
+ /* @__PURE__ */ jsxRuntime.jsx(
9919
+ "div",
9920
+ {
9921
+ className: "canvas-react-tour-backdrop",
9922
+ style: holes.length ? { background: "transparent" } : void 0,
9923
+ onClick: onClose,
9924
+ "aria-hidden": "true"
9925
+ }
9926
+ ),
9927
+ holes.length ? /* @__PURE__ */ jsxRuntime.jsxs(
9928
+ "svg",
9929
+ {
9930
+ className: "canvas-react-tour-mask",
9931
+ "aria-hidden": "true",
9932
+ width: "100%",
9933
+ height: "100%",
9934
+ children: [
9935
+ /* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsxs("mask", { id: maskId.current, maskUnits: "userSpaceOnUse", children: [
9936
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { width: "100%", height: "100%", fill: "white" }),
9937
+ [focus, secondaryFocus].map((hole, index) => /* @__PURE__ */ jsxRuntime.jsx(
9938
+ "rect",
9939
+ {
9940
+ "data-tour-mask-hole": index,
9941
+ x: hole?.left ?? 0,
9942
+ y: hole?.top ?? 0,
9943
+ width: hole?.width ?? 0,
9944
+ height: hole?.height ?? 0,
9945
+ rx: "8",
9946
+ fill: "black"
9947
+ },
9948
+ index
9949
+ ))
9950
+ ] }) }),
9951
+ /* @__PURE__ */ jsxRuntime.jsx(
9952
+ "rect",
9953
+ {
9954
+ width: "100%",
9955
+ height: "100%",
9956
+ fill: "rgba(15, 23, 42, 0.56)",
9957
+ mask: `url(#${maskId.current})`
9958
+ }
9959
+ )
9960
+ ]
9961
+ }
9962
+ ) : null,
9963
+ focus ? /* @__PURE__ */ jsxRuntime.jsx(
9964
+ "div",
9965
+ {
9966
+ className: "canvas-react-tour-focus",
9967
+ style: focus,
9968
+ "aria-hidden": "true"
9969
+ }
9970
+ ) : null,
9971
+ secondaryFocus ? /* @__PURE__ */ jsxRuntime.jsx(
9972
+ "div",
9973
+ {
9974
+ className: "canvas-react-tour-focus canvas-react-tour-focus-secondary",
9975
+ style: secondaryFocus,
9976
+ "aria-hidden": "true"
9977
+ }
9978
+ ) : null,
9979
+ /* @__PURE__ */ jsxRuntime.jsxs(
9980
+ "div",
9981
+ {
9982
+ ref: cardRef,
9983
+ className: "canvas-react-tour-card",
9984
+ role: "dialog",
9985
+ "aria-modal": "true",
9986
+ "aria-label": "\u64CD\u4F5C\u6307\u5F15",
9987
+ tabIndex: -1,
9988
+ style: { top, left },
9989
+ children: [
9990
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "canvas-react-tour-heading", children: [
9991
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
9992
+ current + 1,
9993
+ " / ",
9994
+ steps.length
9995
+ ] }),
9996
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: onClose, "aria-label": "\u5173\u95ED\u6307\u5F15", children: "\xD7" })
9997
+ ] }),
9998
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "canvas-react-tour-content", children: [
9999
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { children: step.title }),
10000
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "canvas-react-tour-description", children: step.description })
10001
+ ] }, current),
10002
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "canvas-react-tour-progress", "aria-label": "\u6307\u5F15\u8FDB\u5EA6", children: steps.map((_, index) => /* @__PURE__ */ jsxRuntime.jsx(
10003
+ "button",
10004
+ {
10005
+ type: "button",
10006
+ className: index === current ? "active" : "",
10007
+ "aria-label": `\u7B2C ${index + 1} \u6B65`,
10008
+ "aria-current": index === current ? "step" : void 0,
10009
+ onClick: () => onChange(index)
10010
+ },
10011
+ index
10012
+ )) }),
10013
+ onPlayingChange && steps.length > 1 ? /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "canvas-react-tour-start-step", children: [
10014
+ "\u4ECE\u7B2C",
10015
+ /* @__PURE__ */ jsxRuntime.jsx(
10016
+ "input",
10017
+ {
10018
+ type: "number",
10019
+ min: 1,
10020
+ max: steps.length,
10021
+ step: 1,
10022
+ value: startStep,
10023
+ onChange: (event) => setStartStep(event.target.value),
10024
+ "aria-label": "\u64AD\u653E\u8D77\u59CB\u6B65\u9AA4"
10025
+ }
10026
+ ),
10027
+ "/ ",
10028
+ steps.length,
10029
+ " \u6B65\u5F00\u59CB\u64AD\u653E"
10030
+ ] }) : null,
10031
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "canvas-react-tour-actions", children: [
10032
+ /* @__PURE__ */ jsxRuntime.jsx(
10033
+ "button",
10034
+ {
10035
+ type: "button",
10036
+ disabled: current === 0,
10037
+ onClick: () => onChange(current - 1),
10038
+ children: "\u4E0A\u4E00\u6B65"
10039
+ }
10040
+ ),
10041
+ onPlayingChange ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: playFromSelectedStep, children: playing ? "\u6682\u505C" : current === steps.length - 1 && startStep === "1" ? "\u91CD\u64AD" : "\u64AD\u653E" }) : null,
10042
+ /* @__PURE__ */ jsxRuntime.jsx(
10043
+ "button",
10044
+ {
10045
+ type: "button",
10046
+ onClick: () => current === steps.length - 1 ? onClose() : onChange(current + 1),
10047
+ children: current === steps.length - 1 ? "\u5B8C\u6210" : "\u4E0B\u4E00\u6B65"
10048
+ }
10049
+ )
10050
+ ] })
10051
+ ]
10052
+ }
10053
+ )
10054
+ ]
10055
+ }
10056
+ ),
10057
+ document.fullscreenElement ?? document.body
10058
+ );
10059
+ }
9474
10060
 
9475
10061
  // src/components/quarter/style.css
9476
10062
  styleInject('@import "../year/style.css";\n.canvas-react-quarter-grid {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 12px 8px;\n}\n.canvas-react-quarter-cell {\n height: 56px;\n font-size: 16px;\n font-weight: 600;\n}\n');
@@ -10146,7 +10732,7 @@ function resolveResizablePanelSizes(params) {
10146
10732
  safeBeforeMax - startBeforeSize,
10147
10733
  startAfterSize - safeAfterMin
10148
10734
  );
10149
- const safeDelta = clamp3(
10735
+ const safeDelta = clamp4(
10150
10736
  Number.isFinite(delta) ? delta : 0,
10151
10737
  minDelta,
10152
10738
  maxDelta
@@ -10198,7 +10784,7 @@ function normalizeOptionalSize(value, minSize, maxSize) {
10198
10784
  if (typeof value !== "number" || !Number.isFinite(value)) {
10199
10785
  return void 0;
10200
10786
  }
10201
- return clamp3(value, minSize, maxSize);
10787
+ return clamp4(value, minSize, maxSize);
10202
10788
  }
10203
10789
  function normalizePositiveNumber(value, fallback) {
10204
10790
  return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : fallback;
@@ -10206,7 +10792,7 @@ function normalizePositiveNumber(value, fallback) {
10206
10792
  function normalizeMaxSize(value, minSize) {
10207
10793
  return typeof value === "number" && Number.isFinite(value) ? Math.max(value, minSize) : Number.POSITIVE_INFINITY;
10208
10794
  }
10209
- function clamp3(value, min, max) {
10795
+ function clamp4(value, min, max) {
10210
10796
  if (min > max) {
10211
10797
  return min;
10212
10798
  }
@@ -13594,7 +14180,6 @@ exports.ReactNodeIndexOutlined = ReactNodeIndexOutlined;
13594
14180
  exports.ReactNotificationFilled = ReactNotificationFilled;
13595
14181
  exports.ReactNotificationOutlined = ReactNotificationOutlined;
13596
14182
  exports.ReactNotificationTwoTone = ReactNotificationTwoTone;
13597
- exports.ReactNumberInput = ReactNumberInput;
13598
14183
  exports.ReactNumberOutlined = ReactNumberOutlined;
13599
14184
  exports.ReactOllamaFilled = ReactOllamaFilled;
13600
14185
  exports.ReactOneToOneOutlined = ReactOneToOneOutlined;
@@ -13654,6 +14239,7 @@ exports.ReactProductOutlined = ReactProductOutlined;
13654
14239
  exports.ReactProfileFilled = ReactProfileFilled;
13655
14240
  exports.ReactProfileOutlined = ReactProfileOutlined;
13656
14241
  exports.ReactProfileTwoTone = ReactProfileTwoTone;
14242
+ exports.ReactProgress = ReactProgress;
13657
14243
  exports.ReactProjectFilled = ReactProjectFilled;
13658
14244
  exports.ReactProjectOutlined = ReactProjectOutlined;
13659
14245
  exports.ReactProjectTwoTone = ReactProjectTwoTone;
@@ -13842,6 +14428,7 @@ exports.ReactToolFilled = ReactToolFilled;
13842
14428
  exports.ReactToolOutlined = ReactToolOutlined;
13843
14429
  exports.ReactToolTwoTone = ReactToolTwoTone;
13844
14430
  exports.ReactTooltip = ReactTooltip;
14431
+ exports.ReactTour = ReactTour;
13845
14432
  exports.ReactTrademarkCircleFilled = ReactTrademarkCircleFilled;
13846
14433
  exports.ReactTrademarkCircleOutlined = ReactTrademarkCircleOutlined;
13847
14434
  exports.ReactTrademarkCircleTwoTone = ReactTrademarkCircleTwoTone;