@lowentry/mui 1.4.4 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/LICENSE +23 -0
  2. package/dist/index.d.ts +129 -0
  3. package/dist/index.js +720 -0
  4. package/dist/index.js.map +1 -0
  5. package/package.json +82 -73
  6. package/Avatar/index.js +0 -44
  7. package/Avatar/index.js.map +0 -1
  8. package/DatePicker/index.js +0 -166
  9. package/DatePicker/index.js.map +0 -1
  10. package/Dialog/index.js +0 -45
  11. package/Dialog/index.js.map +0 -1
  12. package/InitiallyInvisible/index.js +0 -40
  13. package/InitiallyInvisible/index.js.map +0 -1
  14. package/LeMuiUtils-c46ed1cc.js +0 -34
  15. package/LeMuiUtils-c46ed1cc.js.map +0 -1
  16. package/LoadingSpinner/index.js +0 -10
  17. package/LoadingSpinner/index.js.map +0 -1
  18. package/LoadingSpinner-4ccdb773.js +0 -67
  19. package/LoadingSpinner-4ccdb773.js.map +0 -1
  20. package/LoadingSpinnerWidget/index.js +0 -10
  21. package/LoadingSpinnerWidget/index.js.map +0 -1
  22. package/MenuButton/index.js +0 -63
  23. package/MenuButton/index.js.map +0 -1
  24. package/MuiRoot/index.js +0 -30
  25. package/MuiRoot/index.js.map +0 -1
  26. package/NumericTextField/index.js +0 -108
  27. package/NumericTextField/index.js.map +0 -1
  28. package/RemovableNumericTextField/index.js +0 -48
  29. package/RemovableNumericTextField/index.js.map +0 -1
  30. package/RemovableTextField/index.js +0 -54
  31. package/RemovableTextField/index.js.map +0 -1
  32. package/Submittable/index.js +0 -33
  33. package/Submittable/index.js.map +0 -1
  34. package/TextField/index.js +0 -33
  35. package/TextField/index.js.map +0 -1
  36. package/api-extractor.json +0 -43
  37. package/index.js +0 -38
  38. package/index.js.map +0 -1
  39. package/src/LeMuiUtils.js +0 -52
  40. package/src/components/Avatar.jsx +0 -28
  41. package/src/components/DatePicker.jsx +0 -120
  42. package/src/components/DatePicker.less +0 -32
  43. package/src/components/Dialog.jsx +0 -35
  44. package/src/components/Dialog.less +0 -7
  45. package/src/components/InitiallyInvisible.jsx +0 -20
  46. package/src/components/LoadingSpinner/LoadingSpinner.jsx +0 -51
  47. package/src/components/LoadingSpinner/LoadingSpinner.less +0 -9
  48. package/src/components/LoadingSpinner.jsx +0 -1
  49. package/src/components/LoadingSpinnerWidget.jsx +0 -1
  50. package/src/components/MenuButton.jsx +0 -54
  51. package/src/components/MuiRoot.jsx +0 -23
  52. package/src/components/MuiRoot.less +0 -21
  53. package/src/components/NumericTextField.jsx +0 -115
  54. package/src/components/RemovableNumericTextField.jsx +0 -41
  55. package/src/components/RemovableTextField.jsx +0 -48
  56. package/src/components/Submittable.jsx +0 -41
  57. package/src/components/TextField.jsx +0 -30
  58. package/src/components/TextField.less +0 -4
  59. package/src/index.js +0 -13
  60. package/style-inject.es-1f59c1d0.js +0 -29
  61. package/style-inject.es-1f59c1d0.js.map +0 -1
  62. package/tsconfig.d.ts +0 -1
  63. package/tsconfig.json +0 -39
package/dist/index.js ADDED
@@ -0,0 +1,720 @@
1
+ // src/LeMuiUtils.ts
2
+ import { LeUtils, STRING, INT_LAX } from "@lowentry/utils";
3
+ var HIDDEN_CHAR = "\u200B";
4
+ var LeMuiUtils = {
5
+ onSelectEnsureMinimumOffset: (charactersCount) => {
6
+ const count = Math.max(0, INT_LAX(charactersCount));
7
+ if (count <= 0) {
8
+ return () => {
9
+ };
10
+ }
11
+ return (event) => {
12
+ const target = event.target;
13
+ if (target && (target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement) && "selectionEnd" in target && "selectionStart" in target && "setSelectionRange" in target) {
14
+ const selectionEnd = target.selectionEnd ?? 0;
15
+ const selectionStart = target.selectionStart ?? 0;
16
+ if (selectionEnd < count) {
17
+ target.setSelectionRange(count, count);
18
+ } else if (selectionStart < count) {
19
+ target.setSelectionRange(count, selectionEnd);
20
+ }
21
+ }
22
+ };
23
+ },
24
+ prependHiddenChar: (string) => {
25
+ const str = STRING(string);
26
+ if (str.startsWith(HIDDEN_CHAR)) {
27
+ return str;
28
+ }
29
+ return HIDDEN_CHAR + str;
30
+ },
31
+ purgePrependedHiddenChar: (string) => {
32
+ const str = STRING(string);
33
+ return LeUtils.trimStart(str, ["\u200B", " ", " ", "\r", "\n"]);
34
+ }
35
+ };
36
+
37
+ // src/components/Avatar.tsx
38
+ import { memo, useRetryingImageUrl, useCallback } from "@lowentry/react-redux";
39
+ import MuiAvatar from "@mui/material/Avatar";
40
+ import { jsx } from "react/jsx-runtime";
41
+ var Avatar = memo(({ src, slotProps, retryOptions, children, ...props }) => {
42
+ const [imgSrc, onImgError] = useRetryingImageUrl(src ?? "", retryOptions ?? {});
43
+ const onError = useCallback(
44
+ (event) => {
45
+ onImgError();
46
+ if (slotProps?.img?.onError) {
47
+ slotProps.img.onError(event);
48
+ }
49
+ },
50
+ // eslint-disable-next-line react-hooks/exhaustive-deps
51
+ [onImgError, slotProps?.img?.onError]
52
+ );
53
+ return /* @__PURE__ */ jsx(
54
+ MuiAvatar,
55
+ {
56
+ src: imgSrc,
57
+ slotProps: {
58
+ ...slotProps ?? {},
59
+ img: {
60
+ referrerPolicy: "no-referrer",
61
+ ...slotProps?.img ?? {},
62
+ onError
63
+ }
64
+ },
65
+ ...props,
66
+ children
67
+ }
68
+ );
69
+ });
70
+
71
+ // src/components/DatePicker.tsx
72
+ import React from "react";
73
+ import { memo as memo2, useMemo, useCallback as useCallback2, useHistoryState } from "@lowentry/react-redux";
74
+ import { IS_ARRAY, STRING as STRING2 } from "@lowentry/utils";
75
+ import Dayjs from "dayjs";
76
+ import Button from "@mui/material/Button";
77
+ import Stack from "@mui/material/Stack";
78
+ import TextField from "@mui/material/TextField";
79
+ import { DatePicker as MuiDatePicker } from "@mui/x-date-pickers/DatePicker";
80
+ import ArrowBackIosNewIcon from "@mui/icons-material/ArrowBackIosNew";
81
+ import ArrowForwardIosIcon from "@mui/icons-material/ArrowForwardIos";
82
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
83
+ var isReactElement = (val) => {
84
+ return React.isValidElement(val);
85
+ };
86
+ var DatePickerTextField = memo2(({ dateFormat, value, className, ownerState, ...props }) => {
87
+ const onClick = useMemo(() => {
88
+ if (ownerState?.open) {
89
+ return void 0;
90
+ }
91
+ const inputProps2 = props.InputProps;
92
+ if (!inputProps2?.endAdornment) {
93
+ return null;
94
+ }
95
+ const endAdornment = inputProps2.endAdornment;
96
+ if (!isReactElement(endAdornment)) {
97
+ return null;
98
+ }
99
+ let propsLoop = endAdornment.props;
100
+ while (propsLoop && typeof propsLoop === "object") {
101
+ const recordLoop = propsLoop;
102
+ if ("onClick" in recordLoop && typeof recordLoop.onClick === "function") {
103
+ return recordLoop.onClick;
104
+ }
105
+ if ("children" in recordLoop && recordLoop.children) {
106
+ propsLoop = recordLoop.children;
107
+ continue;
108
+ }
109
+ if (IS_ARRAY(propsLoop)) {
110
+ let continueLoop = false;
111
+ for (const propsLoopItem of propsLoop) {
112
+ if (isReactElement(propsLoopItem)) {
113
+ const itemProps = propsLoopItem.props;
114
+ if (itemProps && typeof itemProps === "object") {
115
+ propsLoop = itemProps;
116
+ continueLoop = true;
117
+ }
118
+ }
119
+ }
120
+ if (continueLoop) {
121
+ continue;
122
+ }
123
+ }
124
+ if (isReactElement(propsLoop)) {
125
+ const nextProps = propsLoop.props;
126
+ if (nextProps && typeof nextProps === "object") {
127
+ propsLoop = nextProps;
128
+ } else {
129
+ break;
130
+ }
131
+ } else {
132
+ break;
133
+ }
134
+ }
135
+ return null;
136
+ }, [ownerState, props.InputProps]);
137
+ const onSelect = useCallback2((event) => {
138
+ const target = event.target;
139
+ if (target && target instanceof HTMLInputElement) {
140
+ target.selectionStart = target.selectionEnd;
141
+ }
142
+ event.preventDefault();
143
+ }, []);
144
+ const inputProps = props.InputProps ?? {};
145
+ const formattedValue = useMemo(() => {
146
+ if (value === null || value === void 0) {
147
+ return "";
148
+ }
149
+ return Dayjs(value).format(STRING2(dateFormat));
150
+ }, [value, dateFormat]);
151
+ return /* @__PURE__ */ jsx2(Button, { variant: "outlined", onClick: onClick ?? void 0, children: /* @__PURE__ */ jsx2(
152
+ TextField,
153
+ {
154
+ ...props,
155
+ className: "lowentry-mui--date-picker--textfield " + (STRING2(className) ?? ""),
156
+ variant: "outlined",
157
+ value: formattedValue,
158
+ InputProps: {
159
+ ...inputProps,
160
+ readOnly: true,
161
+ endAdornment: null,
162
+ onSelect,
163
+ onSelectCapture: onSelect,
164
+ onMouseDown: onSelect,
165
+ onTouchStart: onSelect,
166
+ onTouchMove: onSelect
167
+ }
168
+ }
169
+ ) });
170
+ });
171
+ var DatePicker = memo2(({ value, dateFormat, onChange, className, children, ...props }) => {
172
+ const textFieldProps = useMemo(() => {
173
+ if (!dateFormat) {
174
+ return { dateFormat: "ddd, D MMM YYYY" };
175
+ }
176
+ return { dateFormat };
177
+ }, [dateFormat]);
178
+ const [datepickerOpen, openDatepicker, closeDatepicker] = useHistoryState(false);
179
+ const onChanged = useCallback2(
180
+ (value2) => {
181
+ if (onChange) {
182
+ onChange(value2);
183
+ }
184
+ },
185
+ [onChange]
186
+ );
187
+ return /* @__PURE__ */ jsxs(
188
+ Stack,
189
+ {
190
+ className: "lowentry-mui--date-picker " + (className ?? ""),
191
+ direction: "row",
192
+ justifyContent: "space-between",
193
+ spacing: 1,
194
+ ...props,
195
+ children: [
196
+ /* @__PURE__ */ jsx2(
197
+ Button,
198
+ {
199
+ className: "lowentry-mui--date-picker--arrow-button",
200
+ variant: "text",
201
+ color: "primary",
202
+ onClick: () => onChanged(Dayjs(value).subtract(1, "day")),
203
+ children: /* @__PURE__ */ jsx2(ArrowBackIosNewIcon, {})
204
+ }
205
+ ),
206
+ /* @__PURE__ */ jsx2(
207
+ MuiDatePicker,
208
+ {
209
+ open: datepickerOpen,
210
+ onOpen: openDatepicker,
211
+ onClose: closeDatepicker,
212
+ showDaysOutsideCurrentMonth: true,
213
+ views: ["day"],
214
+ format: "YYYY-MM-DD",
215
+ enableAccessibleFieldDOMStructure: false,
216
+ label: "",
217
+ value: value ? Dayjs(value) : null,
218
+ onChange: onChanged,
219
+ slots: {
220
+ textField: DatePickerTextField,
221
+ toolbar: () => null
222
+ },
223
+ slotProps: {
224
+ textField: {
225
+ dateFormat: textFieldProps.dateFormat
226
+ }
227
+ }
228
+ }
229
+ ),
230
+ /* @__PURE__ */ jsx2(
231
+ Button,
232
+ {
233
+ className: "lowentry-mui--date-picker--arrow-button",
234
+ variant: "text",
235
+ color: "primary",
236
+ onClick: () => onChanged(Dayjs(value).add(1, "day")),
237
+ children: /* @__PURE__ */ jsx2(ArrowForwardIosIcon, {})
238
+ }
239
+ ),
240
+ children
241
+ ]
242
+ }
243
+ );
244
+ });
245
+
246
+ // src/components/Dialog.tsx
247
+ import { memo as memo3, useMemo as useMemo2, useCallback as useCallback3 } from "@lowentry/react-redux";
248
+ import { LeUtils as LeUtils2, STRING as STRING3 } from "@lowentry/utils";
249
+ import MuiDialog from "@mui/material/Dialog";
250
+ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
251
+ var Dialog = memo3(({ onClose, children, "aria-label": ariaLabel, open, ...props }) => {
252
+ const ariaLabelId = useMemo2(() => "lowentrymui_dialog_arialabel_" + LeUtils2.uniqueId(), []);
253
+ const onClosed = useCallback3(
254
+ (event, reason) => {
255
+ if (!STRING3(reason).toLowerCase().includes("escape")) {
256
+ return;
257
+ }
258
+ if (onClose) {
259
+ onClose(event, reason);
260
+ }
261
+ },
262
+ [onClose]
263
+ );
264
+ return /* @__PURE__ */ jsxs2(MuiDialog, { className: "lowentry-mui--dialog", onClose: onClosed, "aria-labelledby": ariaLabelId, open: open ?? false, ...props, children: [
265
+ /* @__PURE__ */ jsx3("span", { className: "lowentry-mui--dialog--arialabel", id: ariaLabelId, style: { display: "none" }, children: ariaLabel ?? "" }),
266
+ children
267
+ ] });
268
+ });
269
+
270
+ // src/components/InitiallyInvisible.tsx
271
+ import { memo as memo4, useState, useEffect } from "@lowentry/react-redux";
272
+ import { LeUtils as LeUtils3, INT_LAX as INT_LAX2 } from "@lowentry/utils";
273
+ import { jsx as jsx4 } from "react/jsx-runtime";
274
+ var InitiallyInvisible = memo4(
275
+ ({ frames, transition, style, children, opacityKey, ...other }) => {
276
+ const [opacity, setOpacity] = useState(0);
277
+ useEffect(() => {
278
+ setOpacity(0);
279
+ return LeUtils3.setAnimationFrameTimeout(() => setOpacity(1), Math.max(opacityKey ? 2 : 0, INT_LAX2(frames))).remove;
280
+ }, [opacityKey, frames]);
281
+ return /* @__PURE__ */ jsx4(
282
+ "div",
283
+ {
284
+ style: {
285
+ width: "100%",
286
+ height: "100%",
287
+ opacity,
288
+ transition: opacity > 0 && transition ? "opacity " + transition : "none",
289
+ ...style ?? {}
290
+ },
291
+ ...other,
292
+ children
293
+ }
294
+ );
295
+ }
296
+ );
297
+
298
+ // src/components/LoadingSpinner/LoadingSpinner.tsx
299
+ import { memo as memo5, useEffect as useEffect2, trigger, useTriggerable } from "@lowentry/react-redux";
300
+ import Backdrop from "@mui/material/Backdrop";
301
+ import CircularProgress from "@mui/material/CircularProgress";
302
+ import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
303
+ var loadingSpinnerCount = {};
304
+ var LoadingSpinnerGrab = ({ type }) => {
305
+ loadingSpinnerCount[type] = (loadingSpinnerCount[type] || 0) + 1;
306
+ if (loadingSpinnerCount[type] === 1) {
307
+ trigger("lowentry-mui--loading-spinner--" + type, {});
308
+ }
309
+ };
310
+ var LoadingSpinnerRelease = ({ type }) => {
311
+ loadingSpinnerCount[type] = (loadingSpinnerCount[type] || 1) - 1;
312
+ if (loadingSpinnerCount[type] === 0) {
313
+ trigger("lowentry-mui--loading-spinner--" + type, {});
314
+ }
315
+ };
316
+ var LoadingSpinner = memo5(({ type }) => {
317
+ useEffect2(() => {
318
+ LoadingSpinnerGrab({ type });
319
+ return () => LoadingSpinnerRelease({ type });
320
+ }, [type]);
321
+ return null;
322
+ });
323
+ var LoadingSpinnerWidget = memo5(({ type, className, sx, children, ...props }) => {
324
+ useTriggerable("lowentry-mui--loading-spinner--" + type);
325
+ return /* @__PURE__ */ jsxs3(
326
+ Backdrop,
327
+ {
328
+ className: "lowentry-mui--loading-spinner lowentry-mui--loading-spinner--" + type + " " + (className ?? ""),
329
+ sx: { zIndex: (theme) => theme.zIndex.drawer + 1, ...sx ?? {} },
330
+ open: (loadingSpinnerCount[type] || 0) > 0,
331
+ ...props,
332
+ children: [
333
+ /* @__PURE__ */ jsx5(CircularProgress, { color: "inherit", size: "min(120px,30vw)" }),
334
+ children
335
+ ]
336
+ }
337
+ );
338
+ });
339
+
340
+ // src/components/MenuButton.tsx
341
+ import React2, { cloneElement } from "react";
342
+ import { memo as memo6, useRef, useState as useState2, useCallback as useCallback4, mergeRefs } from "@lowentry/react-redux";
343
+ import { LeUtils as LeUtils4, ARRAY } from "@lowentry/utils";
344
+ import Button2 from "@mui/material/Button";
345
+ import Menu from "@mui/material/Menu";
346
+ import { Fragment, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
347
+ var MenuButton = memo6(({ icon, className, ref, onClick, onClose, children, ...props }) => {
348
+ const buttonRef = useRef(null);
349
+ const [open, setOpen] = useState2(false);
350
+ const onClicked = useCallback4(
351
+ (event) => {
352
+ setOpen(true);
353
+ if (onClick) {
354
+ onClick(event);
355
+ }
356
+ },
357
+ [onClick]
358
+ );
359
+ const onClosed = useCallback4(
360
+ (event) => {
361
+ setOpen(false);
362
+ if (onClose) {
363
+ onClose(event);
364
+ }
365
+ },
366
+ [onClose]
367
+ );
368
+ return /* @__PURE__ */ jsxs4(Fragment, { children: [
369
+ /* @__PURE__ */ jsx6(
370
+ Button2,
371
+ {
372
+ ref: mergeRefs(buttonRef, ref ?? null),
373
+ className: "lowentry-mui--menu-button " + (className ?? ""),
374
+ variant: "text",
375
+ color: "primary",
376
+ onClick: onClicked,
377
+ ...props,
378
+ children: icon
379
+ }
380
+ ),
381
+ /* @__PURE__ */ jsx6(Menu, {
382
+ anchorEl: buttonRef.current,
383
+ open,
384
+ onClose: onClosed,
385
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Dynamic children mapping
386
+ children: LeUtils4.mapToArray(ARRAY(children), (child, index) => {
387
+ if (!child || !React2.isValidElement(child)) {
388
+ return null;
389
+ }
390
+ const indexNum = typeof index === "number" ? index : 0;
391
+ const isRecordLike = (value) => typeof value === "object" && value !== null;
392
+ const childProps = isRecordLike(child.props) ? child.props : {};
393
+ const hasOnClick = "onClick" in childProps && typeof childProps.onClick === "function";
394
+ const hasDisabled = "disabled" in childProps && typeof childProps.disabled === "boolean";
395
+ const newProps = {
396
+ ...childProps,
397
+ key: indexNum,
398
+ onClick: () => {
399
+ setOpen(false);
400
+ if (hasOnClick && typeof childProps.onClick === "function") {
401
+ const clickHandler = childProps.onClick;
402
+ clickHandler();
403
+ }
404
+ },
405
+ disabled: hasDisabled ? !!childProps.disabled : !hasOnClick
406
+ };
407
+ return cloneElement(child, newProps);
408
+ })
409
+ })
410
+ ] });
411
+ });
412
+
413
+ // src/components/MuiRoot.tsx
414
+ import { memo as memo7 } from "@lowentry/react-redux";
415
+ import CssBaseline from "@mui/material/CssBaseline";
416
+ import { ThemeProvider } from "@mui/material/styles";
417
+ import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider";
418
+ import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
419
+ import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
420
+ var MuiRoot = memo7(({ theme, className, children, ...props }) => {
421
+ return /* @__PURE__ */ jsxs5(Fragment2, { children: [
422
+ /* @__PURE__ */ jsx7(CssBaseline, {}),
423
+ /* @__PURE__ */ jsx7(ThemeProvider, { theme, children: /* @__PURE__ */ jsx7(LocalizationProvider, { dateAdapter: AdapterDayjs, children: /* @__PURE__ */ jsx7("div", { className: "lowentry-mui--mui-root " + (className ?? ""), ...props, children }) }) })
424
+ ] });
425
+ });
426
+
427
+ // src/components/NumericTextField.tsx
428
+ import { memo as memo9, useCallback as useCallback6, useState as useState3, useEffect as useEffect3 } from "@lowentry/react-redux";
429
+ import { FLOAT_LAX, INT_LAX_ANY, STRING as STRING4 } from "@lowentry/utils";
430
+
431
+ // src/components/TextField.tsx
432
+ import { memo as memo8, useCallback as useCallback5 } from "@lowentry/react-redux";
433
+ import MuiTextField from "@mui/material/TextField";
434
+ import { jsx as jsx8 } from "react/jsx-runtime";
435
+ var TextField2 = memo8(({ className, onClick, children, ...props }) => {
436
+ const onClicked = useCallback5(
437
+ (event) => {
438
+ try {
439
+ event.stopPropagation();
440
+ } catch {
441
+ }
442
+ if (onClick) {
443
+ onClick(event);
444
+ }
445
+ },
446
+ [onClick]
447
+ );
448
+ return /* @__PURE__ */ jsx8(
449
+ MuiTextField,
450
+ {
451
+ className: "lowentry-mui--textfield " + (className ?? ""),
452
+ autoComplete: "off",
453
+ onClick: onClicked,
454
+ ...props,
455
+ children
456
+ }
457
+ );
458
+ });
459
+ var TextField_default = TextField2;
460
+
461
+ // src/components/NumericTextField.tsx
462
+ import { jsx as jsx9 } from "react/jsx-runtime";
463
+ var getProcessedValue = (value, decimals, allowZero, allowNegative) => {
464
+ let text = LeMuiUtils.purgePrependedHiddenChar(STRING4(value));
465
+ let val = 0;
466
+ const negative = text.includes("-");
467
+ text = text.replace(",", ".").replace(/[^0-9.]/g, "");
468
+ if (text !== "") {
469
+ let stringVal = Math.abs(FLOAT_LAX(text)).toFixed(decimals + 1);
470
+ stringVal = stringVal.substring(0, stringVal.length - 1);
471
+ const textDotCount = text.split(".").length - 1;
472
+ if (textDotCount <= 0 || decimals <= 0) {
473
+ text = stringVal.split(".")[0];
474
+ } else if (textDotCount === 1 && text.endsWith(".")) {
475
+ text = stringVal.split(".")[0] + ".";
476
+ } else {
477
+ text = stringVal.substring(0, stringVal.length - Math.max(0, decimals - text.split(".")[1].length));
478
+ }
479
+ if (!allowZero && text === "0") {
480
+ text = "";
481
+ }
482
+ }
483
+ if (allowNegative && negative) {
484
+ text = "-" + text;
485
+ }
486
+ val = FLOAT_LAX(text);
487
+ if (val !== 0) {
488
+ if (decimals > 0) {
489
+ val = Math.round(val * Math.pow(10, decimals)) / Math.pow(10, decimals);
490
+ } else {
491
+ val = Math.round(val);
492
+ }
493
+ }
494
+ return { text, val };
495
+ };
496
+ var NumericTextField = memo9(
497
+ ({
498
+ decimals: decimalsProp,
499
+ allowZero: allowZeroProp,
500
+ allowNegative: allowNegativeProp,
501
+ value,
502
+ onChange,
503
+ onRenderValue,
504
+ className,
505
+ inputProps,
506
+ children,
507
+ ...props
508
+ }) => {
509
+ const allowZero = !!allowZeroProp;
510
+ const allowNegative = !!allowNegativeProp;
511
+ const decimals = INT_LAX_ANY(decimalsProp, 0);
512
+ const getVisualValue = useCallback6(
513
+ (val) => {
514
+ return getProcessedValue(val, decimals, allowZero, allowNegative).text;
515
+ },
516
+ [decimals, allowZero, allowNegative]
517
+ );
518
+ const [visualValue, setVisualValue] = useState3(getVisualValue(value));
519
+ useEffect3(() => {
520
+ const newVisualValue = getVisualValue(value);
521
+ if (FLOAT_LAX(visualValue) !== FLOAT_LAX(newVisualValue)) {
522
+ setVisualValue(newVisualValue);
523
+ }
524
+ }, [value, getVisualValue]);
525
+ const onChanged = useCallback6(
526
+ (event) => {
527
+ const originalTargetValue = event.target.value;
528
+ const { text, val } = getProcessedValue(originalTargetValue, decimals, allowZero, allowNegative);
529
+ setVisualValue(text);
530
+ if (onChange) {
531
+ const newTarget = {
532
+ ...event.target,
533
+ value: val,
534
+ valueText: text,
535
+ valueRaw: originalTargetValue
536
+ };
537
+ const newEvent = {
538
+ ...event,
539
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Custom event target augmentation
540
+ target: newTarget
541
+ };
542
+ onChange(newEvent);
543
+ }
544
+ },
545
+ [onChange, decimals, allowZero, allowNegative]
546
+ );
547
+ return /* @__PURE__ */ jsx9(
548
+ TextField_default,
549
+ {
550
+ className: "lowentry-mui--numeric-textfield " + (className ?? ""),
551
+ type: "text",
552
+ inputProps: { inputMode: "decimal", ...inputProps ?? {} },
553
+ value: onRenderValue ? onRenderValue(visualValue) : visualValue,
554
+ onChange: onChanged,
555
+ ...props,
556
+ children
557
+ }
558
+ );
559
+ }
560
+ );
561
+ var NumericTextField_default = NumericTextField;
562
+
563
+ // src/components/RemovableNumericTextField.tsx
564
+ import { memo as memo10, useCallback as useCallback7 } from "@lowentry/react-redux";
565
+ import { jsx as jsx10 } from "react/jsx-runtime";
566
+ var RemovableNumericTextField = memo10(
567
+ ({ onRemove, onChange, onSelect, className, children, ...props }) => {
568
+ const onChanged = useCallback7(
569
+ (event) => {
570
+ if (event.target.valueRaw === "") {
571
+ if (onRemove) {
572
+ onRemove(event);
573
+ }
574
+ return;
575
+ }
576
+ if (onChange) {
577
+ onChange(event);
578
+ }
579
+ },
580
+ [onRemove, onChange]
581
+ );
582
+ const onSelected = useCallback7(
583
+ (event) => {
584
+ LeMuiUtils.onSelectEnsureMinimumOffset(1)(event);
585
+ if (onSelect) {
586
+ onSelect(event);
587
+ }
588
+ },
589
+ [onSelect]
590
+ );
591
+ const onSelectedWrapper = useCallback7(
592
+ (event) => {
593
+ const target = event.target;
594
+ if (target && (target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement)) {
595
+ Function.prototype.call.call(onSelected, void 0, {
596
+ ...event,
597
+ target,
598
+ currentTarget: target
599
+ });
600
+ }
601
+ },
602
+ [onSelected]
603
+ );
604
+ return /* @__PURE__ */ jsx10(
605
+ NumericTextField_default,
606
+ {
607
+ className: "lowentry-mui--removable-textfield lowentry-mui--removable-numeric-textfield " + (className ?? ""),
608
+ onRenderValue: LeMuiUtils.prependHiddenChar,
609
+ onChange: onChanged,
610
+ onSelect: onSelectedWrapper,
611
+ ...props,
612
+ children
613
+ }
614
+ );
615
+ }
616
+ );
617
+
618
+ // src/components/RemovableTextField.tsx
619
+ import { memo as memo11, useCallback as useCallback8 } from "@lowentry/react-redux";
620
+ import { jsx as jsx11 } from "react/jsx-runtime";
621
+ var RemovableTextField = memo11(
622
+ ({ className, value, onRemove, onChange, onSelect, children, ...props }) => {
623
+ const onChanged = useCallback8(
624
+ (event) => {
625
+ if (event.target.value === "") {
626
+ if (onRemove) {
627
+ onRemove(event);
628
+ }
629
+ return;
630
+ }
631
+ if (onChange) {
632
+ const newEvent = {
633
+ ...event,
634
+ target: {
635
+ ...event.target,
636
+ value: LeMuiUtils.purgePrependedHiddenChar(event.target.value)
637
+ }
638
+ };
639
+ onChange(newEvent);
640
+ }
641
+ },
642
+ [onRemove, onChange]
643
+ );
644
+ const onSelected = useCallback8(
645
+ (event) => {
646
+ LeMuiUtils.onSelectEnsureMinimumOffset(1)(event);
647
+ if (onSelect) {
648
+ onSelect(event);
649
+ }
650
+ },
651
+ [onSelect]
652
+ );
653
+ const onSelectedWrapper = useCallback8(
654
+ (event) => {
655
+ const target = event.target;
656
+ if (target && (target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement)) {
657
+ Function.prototype.call.call(onSelected, void 0, {
658
+ ...event,
659
+ target,
660
+ currentTarget: target
661
+ });
662
+ }
663
+ },
664
+ [onSelected]
665
+ );
666
+ return /* @__PURE__ */ jsx11(
667
+ TextField_default,
668
+ {
669
+ className: "lowentry-mui--removable-textfield " + (className ?? ""),
670
+ value: LeMuiUtils.prependHiddenChar(String(value ?? "")),
671
+ onChange: onChanged,
672
+ onSelect: onSelectedWrapper,
673
+ ...props,
674
+ children
675
+ }
676
+ );
677
+ }
678
+ );
679
+
680
+ // src/components/Submittable.tsx
681
+ import { memo as memo12, useCallback as useCallback9 } from "@lowentry/react-redux";
682
+ import Stack2 from "@mui/material/Stack";
683
+ import { jsx as jsx12 } from "react/jsx-runtime";
684
+ var Submittable = memo12(({ onSubmit, disabled, sx, children, ...props }) => {
685
+ const handleSubmit = useCallback9(
686
+ (event) => {
687
+ try {
688
+ event.preventDefault();
689
+ } catch {
690
+ }
691
+ if (disabled) {
692
+ if (!(typeof disabled === "function") || disabled()) {
693
+ return;
694
+ }
695
+ }
696
+ if (onSubmit) {
697
+ onSubmit(event);
698
+ }
699
+ },
700
+ [onSubmit, disabled]
701
+ );
702
+ return /* @__PURE__ */ jsx12("form", { style: sx, onSubmit: handleSubmit, children: /* @__PURE__ */ jsx12(Stack2, { ...props, children }) });
703
+ });
704
+ export {
705
+ Avatar,
706
+ DatePicker,
707
+ Dialog,
708
+ InitiallyInvisible,
709
+ LeMuiUtils,
710
+ LoadingSpinner,
711
+ LoadingSpinnerWidget,
712
+ MenuButton,
713
+ MuiRoot,
714
+ NumericTextField,
715
+ RemovableNumericTextField,
716
+ RemovableTextField,
717
+ Submittable,
718
+ TextField2 as TextField
719
+ };
720
+ //# sourceMappingURL=index.js.map