@officesdk/design 0.2.6 → 0.2.8

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.
@@ -73,6 +73,159 @@ interface ButtonProps extends React$1.ButtonHTMLAttributes<HTMLButtonElement> {
73
73
  */
74
74
  declare const Button: React$1.FC<ButtonProps>;
75
75
 
76
+ /**
77
+ * Value map utilities for piecewise linear mapping (non-linear slider)
78
+ */
79
+ interface ValueMapPiece {
80
+ /** Size of the piece (value range) */
81
+ size: number;
82
+ /** Step increment, defaults to 1 */
83
+ step?: number;
84
+ /** Visual size (relative), defaults to size/step */
85
+ visualSize?: number;
86
+ }
87
+ interface ValueMap {
88
+ type: 'piecewise';
89
+ /** Starting value */
90
+ start: number;
91
+ /** Array of pieces defining the mapping */
92
+ pieces: ValueMapPiece[];
93
+ }
94
+
95
+ type LineType$1 = 'outlined' | 'underlined' | 'borderless';
96
+ interface NumberInputProps {
97
+ /**
98
+ * Current value
99
+ */
100
+ value?: number;
101
+ /**
102
+ * Default value
103
+ */
104
+ defaultValue?: number;
105
+ /**
106
+ * Minimum value
107
+ */
108
+ min?: number;
109
+ /**
110
+ * Maximum value
111
+ */
112
+ max?: number;
113
+ /**
114
+ * Step increment/decrement
115
+ */
116
+ step?: number;
117
+ /**
118
+ * Size variant
119
+ */
120
+ size?: 'small' | 'large';
121
+ /**
122
+ * Whether the input is disabled
123
+ */
124
+ disabled?: boolean;
125
+ /**
126
+ * Whether to show alert state (red border)
127
+ */
128
+ alert?: boolean;
129
+ /**
130
+ * Number of decimal places
131
+ */
132
+ precision?: number;
133
+ /**
134
+ * Format the display value
135
+ */
136
+ formatter?: (value: number) => string;
137
+ /**
138
+ * Parse the input value
139
+ */
140
+ parser?: (displayValue: string) => number;
141
+ /**
142
+ * Unit text to display after the input
143
+ */
144
+ unit?: string;
145
+ /**
146
+ * Placeholder text
147
+ */
148
+ placeholder?: string;
149
+ /**
150
+ * Whether to show step buttons (increment/decrement)
151
+ * @default true
152
+ */
153
+ showStepButtons?: boolean;
154
+ /**
155
+ * Trigger mode for showing step buttons
156
+ * - 'normal': always show (default)
157
+ * - 'hover': show only on hover
158
+ * @default 'normal'
159
+ */
160
+ showStepButtonsTrigger?: 'hover' | 'normal';
161
+ /**
162
+ * Input line type
163
+ * - 'outlined': with full border (default)
164
+ * - 'underlined': with bottom border only
165
+ * - 'borderless': no border
166
+ * @default 'outlined'
167
+ */
168
+ lineType?: LineType$1;
169
+ /**
170
+ * Whether to use thousands separator in display
171
+ * @default false
172
+ */
173
+ useThousandsSeparator?: boolean;
174
+ /**
175
+ * Value map for piecewise linear mapping (non-linear stepping)
176
+ * When provided, min/max/step props are ignored
177
+ */
178
+ valueMap?: ValueMap;
179
+ /**
180
+ * Callback when value changes
181
+ * @param fixedValue - The clamped value within min/max range (can be undefined if empty)
182
+ * @param rawValue - The original input value before clamping (can be undefined if empty)
183
+ */
184
+ onChange?: (fixedValue: number | undefined, rawValue: number | undefined) => void;
185
+ /**
186
+ * Custom className
187
+ */
188
+ className?: string;
189
+ /**
190
+ * Custom style
191
+ */
192
+ style?: React$1.CSSProperties;
193
+ /**
194
+ * Callback when input receives focus
195
+ */
196
+ onFocus?: (e: React$1.FocusEvent<HTMLInputElement>) => void;
197
+ /**
198
+ * Callback when input loses focus
199
+ */
200
+ onBlur?: (e: React$1.FocusEvent<HTMLInputElement>) => void;
201
+ /**
202
+ * Callback when input value changes during typing
203
+ * Useful for real-time validation (e.g., check if value is multiple of 3)
204
+ * @param inputValue - The raw input string
205
+ * @param parsedValue - The parsed number value (undefined if invalid)
206
+ */
207
+ onInputChange?: (inputValue: string, parsedValue: number | undefined) => void;
208
+ /**
209
+ * Whether to select all text when the input receives focus
210
+ * @default false
211
+ */
212
+ selectAllOnFocus?: boolean;
213
+ /**
214
+ * Whether to blur the input when Escape key is pressed
215
+ * @default true
216
+ */
217
+ blurOnEscape?: boolean;
218
+ }
219
+ /**
220
+ * NumberInput Component
221
+ *
222
+ * A numeric input with increment/decrement buttons
223
+ *
224
+ * @example
225
+ * <NumberInput value={35} onChange={(val) => console.log(val)} />
226
+ */
227
+ declare const NumberInput: React$1.FC<NumberInputProps>;
228
+
76
229
  interface SpinButtonProps {
77
230
  /**
78
231
  * Current value
@@ -122,6 +275,11 @@ interface SpinButtonProps {
122
275
  * Parse the input value
123
276
  */
124
277
  parser?: (displayValue: string) => number;
278
+ /**
279
+ * Value map for piecewise linear mapping (non-linear stepping)
280
+ * When provided, min/max/step props are ignored in NumberInput and Slider
281
+ */
282
+ valueMap?: ValueMap;
125
283
  /**
126
284
  * Callback when value changes
127
285
  */
@@ -134,6 +292,11 @@ interface SpinButtonProps {
134
292
  * Custom style
135
293
  */
136
294
  style?: React$1.CSSProperties;
295
+ /**
296
+ * Additional props passed to the internal NumberInput component
297
+ * Allows customizing unit, placeholder, lineType, showStepButtons, etc.
298
+ */
299
+ inputProps?: Partial<Omit<NumberInputProps, 'value' | 'defaultValue' | 'min' | 'max' | 'step' | 'size' | 'disabled' | 'alert' | 'precision' | 'formatter' | 'parser' | 'valueMap' | 'onChange' | 'className' | 'style'>>;
137
300
  }
138
301
  /**
139
302
  * SpinButton Component - Spin Button
@@ -301,25 +464,6 @@ interface CheckboxProps {
301
464
  */
302
465
  declare const Checkbox: React$1.FC<CheckboxProps>;
303
466
 
304
- /**
305
- * Value map utilities for piecewise linear mapping (non-linear slider)
306
- */
307
- interface ValueMapPiece {
308
- /** Size of the piece (value range) */
309
- size: number;
310
- /** Step increment, defaults to 1 */
311
- step?: number;
312
- /** Visual size (relative), defaults to size/step */
313
- visualSize?: number;
314
- }
315
- interface ValueMap {
316
- type: 'piecewise';
317
- /** Starting value */
318
- start: number;
319
- /** Array of pieces defining the mapping */
320
- pieces: ValueMapPiece[];
321
- }
322
-
323
467
  interface SliderProps {
324
468
  /**
325
469
  * Current value (0-100)
@@ -386,12 +530,12 @@ interface SliderProps {
386
530
  declare const Slider: React$1.FC<SliderProps>;
387
531
 
388
532
  type InputSize = 'mini' | 'small' | 'medium' | 'large';
389
- type LineType$1 = 'outlined' | 'underlined' | 'borderless';
533
+ type LineType = 'outlined' | 'underlined' | 'borderless';
390
534
  interface InputProps extends Omit<React$1.InputHTMLAttributes<HTMLInputElement>, 'size' | 'prefix'> {
391
535
  /**
392
536
  * Input line type
393
537
  */
394
- lineType?: LineType$1;
538
+ lineType?: LineType;
395
539
  /**
396
540
  * Input size
397
541
  */
@@ -530,110 +674,6 @@ declare const SearchInput: React$1.ForwardRefExoticComponent<SearchInputProps &
530
674
  */
531
675
  declare const UnderlinedInput: React$1.ForwardRefExoticComponent<Omit<InputProps, "lineType"> & React$1.RefAttributes<HTMLInputElement>>;
532
676
 
533
- type LineType = 'outlined' | 'underlined' | 'borderless';
534
- interface NumberInputProps {
535
- /**
536
- * Current value
537
- */
538
- value?: number;
539
- /**
540
- * Default value
541
- */
542
- defaultValue?: number;
543
- /**
544
- * Minimum value
545
- */
546
- min?: number;
547
- /**
548
- * Maximum value
549
- */
550
- max?: number;
551
- /**
552
- * Step increment/decrement
553
- */
554
- step?: number;
555
- /**
556
- * Size variant
557
- */
558
- size?: 'small' | 'large';
559
- /**
560
- * Whether the input is disabled
561
- */
562
- disabled?: boolean;
563
- /**
564
- * Whether to show alert state (red border)
565
- */
566
- alert?: boolean;
567
- /**
568
- * Number of decimal places
569
- */
570
- precision?: number;
571
- /**
572
- * Format the display value
573
- */
574
- formatter?: (value: number) => string;
575
- /**
576
- * Parse the input value
577
- */
578
- parser?: (displayValue: string) => number;
579
- /**
580
- * Unit text to display after the input
581
- */
582
- unit?: string;
583
- /**
584
- * Placeholder text
585
- */
586
- placeholder?: string;
587
- /**
588
- * Whether to show step buttons (increment/decrement)
589
- * @default true
590
- */
591
- showStepButtons?: boolean;
592
- /**
593
- * Trigger mode for showing step buttons
594
- * - 'normal': always show (default)
595
- * - 'hover': show only on hover
596
- * @default 'normal'
597
- */
598
- showStepButtonsTrigger?: 'hover' | 'normal';
599
- /**
600
- * Input line type
601
- * - 'outlined': with full border (default)
602
- * - 'underlined': with bottom border only
603
- * - 'borderless': no border
604
- * @default 'outlined'
605
- */
606
- lineType?: LineType;
607
- /**
608
- * Whether to use thousands separator in display
609
- * @default false
610
- */
611
- useThousandsSeparator?: boolean;
612
- /**
613
- * Callback when value changes
614
- * @param fixedValue - The clamped value within min/max range (can be undefined if empty)
615
- * @param rawValue - The original input value before clamping (can be undefined if empty)
616
- */
617
- onChange?: (fixedValue: number | undefined, rawValue: number | undefined) => void;
618
- /**
619
- * Custom className
620
- */
621
- className?: string;
622
- /**
623
- * Custom style
624
- */
625
- style?: React$1.CSSProperties;
626
- }
627
- /**
628
- * NumberInput Component
629
- *
630
- * A numeric input with increment/decrement buttons
631
- *
632
- * @example
633
- * <NumberInput value={35} onChange={(val) => console.log(val)} />
634
- */
635
- declare const NumberInput: React$1.FC<NumberInputProps>;
636
-
637
677
  interface IconSize {
638
678
  width: string;
639
679
  height: string;
@@ -1620,6 +1620,7 @@ var init_NumberInput = __esm({
1620
1620
  init_styled();
1621
1621
  init_UIConfigProvider2();
1622
1622
  init_numberLocale();
1623
+ init_valueMap();
1623
1624
  getDecimalPlaces = (num) => {
1624
1625
  const str = String(num);
1625
1626
  const decimalIndex = str.indexOf(".");
@@ -1862,9 +1863,15 @@ var init_NumberInput = __esm({
1862
1863
  showStepButtonsTrigger = "normal",
1863
1864
  lineType = "outlined",
1864
1865
  useThousandsSeparator = false,
1866
+ valueMap: valueMapProp,
1865
1867
  onChange,
1866
1868
  className,
1867
- style
1869
+ style,
1870
+ onFocus: onFocusProp,
1871
+ onBlur: onBlurProp,
1872
+ onInputChange,
1873
+ selectAllOnFocus = false,
1874
+ blurOnEscape = true
1868
1875
  }) => {
1869
1876
  const config = exports.useUIConfig();
1870
1877
  const locale = config?.locale ?? "en-US";
@@ -1874,6 +1881,12 @@ var init_NumberInput = __esm({
1874
1881
  const [isHovered, setIsHovered] = React3.useState(false);
1875
1882
  const inputRef = React3.useRef(null);
1876
1883
  const value = controlledValue !== void 0 ? controlledValue : internalValue;
1884
+ const extendedValueMap = React3.useMemo(() => {
1885
+ if (!valueMapProp) return void 0;
1886
+ return extendValueMap(valueMapProp);
1887
+ }, [valueMapProp]);
1888
+ const effectiveMin = extendedValueMap ? extendedValueMap.start : min;
1889
+ const effectiveMax = extendedValueMap ? extendedValueMap.end : max;
1877
1890
  const formatValue = React3.useCallback(
1878
1891
  (val) => {
1879
1892
  if (val === void 0) {
@@ -1930,9 +1943,9 @@ var init_NumberInput = __esm({
1930
1943
  if (val === void 0) {
1931
1944
  return void 0;
1932
1945
  }
1933
- return Math.max(min, Math.min(max, val));
1946
+ return Math.max(effectiveMin, Math.min(effectiveMax, val));
1934
1947
  },
1935
- [min, max]
1948
+ [effectiveMin, effectiveMax]
1936
1949
  );
1937
1950
  const handleValueChange = React3.useCallback(
1938
1951
  (newValue) => {
@@ -1947,46 +1960,67 @@ var init_NumberInput = __esm({
1947
1960
  const increment = React3.useCallback(() => {
1948
1961
  if (disabled) return;
1949
1962
  const currentValue = value ?? 0;
1950
- const newValue = precisionAdd(currentValue, step);
1963
+ const newValue = extendedValueMap ? changeByStep(currentValue, 1, extendedValueMap) : precisionAdd(currentValue, step);
1951
1964
  handleValueChange(newValue);
1952
1965
  if (isFocused) {
1953
1966
  const clampedValue = clampValue(newValue);
1954
1967
  setDisplayValue(formatValueForEdit(clampedValue));
1955
1968
  }
1956
- }, [disabled, value, step, handleValueChange, isFocused, clampValue, formatValueForEdit]);
1969
+ }, [disabled, value, step, handleValueChange, isFocused, clampValue, formatValueForEdit, extendedValueMap]);
1957
1970
  const decrement = React3.useCallback(() => {
1958
1971
  if (disabled) return;
1959
1972
  const currentValue = value ?? 0;
1960
- const newValue = precisionSubtract(currentValue, step);
1973
+ const newValue = extendedValueMap ? changeByStep(currentValue, -1, extendedValueMap) : precisionSubtract(currentValue, step);
1961
1974
  handleValueChange(newValue);
1962
1975
  if (isFocused) {
1963
1976
  const clampedValue = clampValue(newValue);
1964
1977
  setDisplayValue(formatValueForEdit(clampedValue));
1965
1978
  }
1966
- }, [disabled, value, step, handleValueChange, isFocused, clampValue, formatValueForEdit]);
1967
- const handleInputChange = React3.useCallback((e) => {
1968
- setDisplayValue(e.target.value);
1969
- }, []);
1970
- const handleBlur = React3.useCallback(() => {
1971
- setIsFocused(false);
1972
- const trimmedValue = displayValue.trim();
1973
- if (trimmedValue === "") {
1974
- handleValueChange(void 0);
1975
- setDisplayValue("");
1976
- } else {
1977
- const parsed = parseValue(trimmedValue);
1978
- if (parsed !== null) {
1979
- const preciseValue = applyPrecision(parsed);
1980
- handleValueChange(preciseValue);
1979
+ }, [disabled, value, step, handleValueChange, isFocused, clampValue, formatValueForEdit, extendedValueMap]);
1980
+ const handleInputChange = React3.useCallback(
1981
+ (e) => {
1982
+ const inputValue = e.target.value;
1983
+ setDisplayValue(inputValue);
1984
+ const trimmed = inputValue.trim();
1985
+ const parsedValue = trimmed === "" ? void 0 : parseValue(trimmed) ?? void 0;
1986
+ onInputChange?.(inputValue, parsedValue);
1987
+ },
1988
+ [parseValue, onInputChange]
1989
+ );
1990
+ const handleBlur = React3.useCallback(
1991
+ (e) => {
1992
+ setIsFocused(false);
1993
+ const trimmedValue = displayValue.trim();
1994
+ if (trimmedValue === "") {
1995
+ handleValueChange(void 0);
1996
+ setDisplayValue("");
1981
1997
  } else {
1982
- setDisplayValue(formatValue(value));
1998
+ const parsed = parseValue(trimmedValue);
1999
+ if (parsed !== null) {
2000
+ const preciseValue = applyPrecision(parsed);
2001
+ const finalValue = extendedValueMap && preciseValue !== void 0 ? snapToStep(preciseValue, extendedValueMap) : preciseValue;
2002
+ handleValueChange(finalValue);
2003
+ } else {
2004
+ setDisplayValue(formatValue(value));
2005
+ }
1983
2006
  }
1984
- }
1985
- }, [displayValue, parseValue, handleValueChange, value, formatValue, applyPrecision]);
1986
- const handleFocus = React3.useCallback(() => {
1987
- setIsFocused(true);
1988
- setDisplayValue(formatValueForEdit(value));
1989
- }, [value, formatValueForEdit]);
2007
+ onBlurProp?.(e);
2008
+ },
2009
+ [displayValue, parseValue, handleValueChange, value, formatValue, applyPrecision, onBlurProp, extendedValueMap]
2010
+ );
2011
+ const handleFocus = React3.useCallback(
2012
+ (e) => {
2013
+ setIsFocused(true);
2014
+ setDisplayValue(formatValueForEdit(value));
2015
+ if (selectAllOnFocus) {
2016
+ requestAnimationFrame(() => {
2017
+ inputRef.current?.select();
2018
+ });
2019
+ }
2020
+ onFocusProp?.(e);
2021
+ },
2022
+ [value, formatValueForEdit, onFocusProp, selectAllOnFocus]
2023
+ );
1990
2024
  const handleKeyDown = React3.useCallback(
1991
2025
  (e) => {
1992
2026
  if (e.key === "ArrowUp") {
@@ -1997,9 +2031,11 @@ var init_NumberInput = __esm({
1997
2031
  decrement();
1998
2032
  } else if (e.key === "Enter") {
1999
2033
  inputRef.current?.blur();
2034
+ } else if (e.key === "Escape" && blurOnEscape) {
2035
+ inputRef.current?.blur();
2000
2036
  }
2001
2037
  },
2002
- [increment, decrement]
2038
+ [increment, decrement, blurOnEscape]
2003
2039
  );
2004
2040
  const handleMouseEnter = React3.useCallback(() => {
2005
2041
  setIsHovered(true);
@@ -2102,9 +2138,11 @@ var init_SpinButton = __esm({
2102
2138
  precision,
2103
2139
  formatter,
2104
2140
  parser,
2141
+ valueMap,
2105
2142
  onChange,
2106
2143
  className,
2107
- style
2144
+ style,
2145
+ inputProps
2108
2146
  }) => {
2109
2147
  const [internalValue, setInternalValue] = React3.useState(controlledValue ?? defaultValue);
2110
2148
  const value = controlledValue !== void 0 ? controlledValue : internalValue;
@@ -2130,6 +2168,7 @@ var init_SpinButton = __esm({
2130
2168
  max,
2131
2169
  step,
2132
2170
  disabled,
2171
+ valueMap,
2133
2172
  onChange: handleValueChange
2134
2173
  }
2135
2174
  )), /* @__PURE__ */ React3__default.default.createElement(
@@ -2145,6 +2184,8 @@ var init_SpinButton = __esm({
2145
2184
  precision,
2146
2185
  formatter,
2147
2186
  parser,
2187
+ valueMap,
2188
+ ...inputProps,
2148
2189
  onChange: handleValueChange
2149
2190
  }
2150
2191
  ));
@@ -3675,6 +3716,9 @@ Tooltip.displayName = "Tooltip";
3675
3716
 
3676
3717
  // src/ToolbarButton/ToolbarButton.tsx
3677
3718
  init_styled();
3719
+ var ArrowDownIcon = () => {
3720
+ return /* @__PURE__ */ React3__default.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 16 16", fill: "none" }, /* @__PURE__ */ React3__default.default.createElement("path", { d: "M8.1858 9.79353C8.08649 9.90387 7.91346 9.90387 7.81415 9.79353L4.77549 6.41724C4.6307 6.25636 4.74487 6 4.96132 6L11.0386 6C11.2551 6 11.3693 6.25636 11.2245 6.41724L8.1858 9.79353Z", fill: "#41464B", fillOpacity: "0.6" }));
3721
+ };
3678
3722
  var ToolbarButtonContainer = exports.styled.div`
3679
3723
  display: inline-flex;
3680
3724
  align-items: center;
@@ -3975,7 +4019,7 @@ var ToolbarButton = ({
3975
4019
  },
3976
4020
  renderIcon(),
3977
4021
  renderLabel(),
3978
- /* @__PURE__ */ React3__default.default.createElement(DropdownArrow, { $disabled: disabled }, /* @__PURE__ */ React3__default.default.createElement(icons.ArrowDownIcon, null))
4022
+ /* @__PURE__ */ React3__default.default.createElement(DropdownArrow, { $disabled: disabled }, /* @__PURE__ */ React3__default.default.createElement(ArrowDownIcon, null))
3979
4023
  )
3980
4024
  );
3981
4025
  }
@@ -4011,7 +4055,7 @@ var ToolbarButton = ({
4011
4055
  onClick: handleDropdownClick,
4012
4056
  disabled
4013
4057
  },
4014
- /* @__PURE__ */ React3__default.default.createElement(DropdownArrow, { $disabled: disabled }, /* @__PURE__ */ React3__default.default.createElement(icons.ArrowDownIcon, null))
4058
+ /* @__PURE__ */ React3__default.default.createElement(DropdownArrow, { $disabled: disabled }, /* @__PURE__ */ React3__default.default.createElement(ArrowDownIcon, null))
4015
4059
  )
4016
4060
  );
4017
4061
  }