@helpwave/hightide 0.0.17 → 0.0.18

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.
@@ -3,9 +3,8 @@ import { HTMLInputTypeAttribute, InputHTMLAttributes } from 'react';
3
3
 
4
4
  type InputProps = {
5
5
  /**
6
- * used for the label's `for` attribute
6
+ * The value
7
7
  */
8
- id: string;
9
8
  value: string;
10
9
  /**
11
10
  * @default 'text'
@@ -17,19 +16,20 @@ type InputProps = {
17
16
  * That could be enforced through a union type but that seems a bit overkill
18
17
  * @default noop
19
18
  */
20
- onChange?: (text: string) => void;
19
+ onChangeText?: (text: string) => void;
20
+ onEditCompleted?: (text: string) => void;
21
21
  labelClassName?: string;
22
22
  initialState?: 'editing' | 'display';
23
23
  size?: number;
24
24
  disclaimer?: string;
25
- onEditCompleted?: (text: string) => void;
26
- } & Omit<InputHTMLAttributes<HTMLInputElement>, 'id' | 'value' | 'label' | 'type' | 'onChange' | 'crossOrigin'>;
25
+ } & Omit<InputHTMLAttributes<HTMLInputElement>, 'value' | 'label' | 'type' | 'crossOrigin'>;
27
26
  /**
28
27
  * A Text input component for inputting text. It changes appearance upon entering the edit mode and switches
29
28
  * back to display mode on loss of focus or on enter
30
29
  *
31
30
  * The State is managed by the parent
32
31
  */
33
- declare const ToggleableInput: ({ id, type, value, onChange, labelClassName, initialState, size, disclaimer, onBlur, onEditCompleted, ...restProps }: InputProps) => react_jsx_runtime.JSX.Element;
32
+ declare const ToggleableInput: ({ type, value, onChange, onChangeText, onEditCompleted, labelClassName, initialState, size, disclaimer, onBlur, ...restProps }: InputProps) => react_jsx_runtime.JSX.Element;
33
+ declare const ToggleableInputUncontrolled: ({ value: initialValue, onChangeText, ...restProps }: InputProps) => react_jsx_runtime.JSX.Element;
34
34
 
35
- export { ToggleableInput };
35
+ export { ToggleableInput, ToggleableInputUncontrolled };
@@ -3,9 +3,8 @@ import { HTMLInputTypeAttribute, InputHTMLAttributes } from 'react';
3
3
 
4
4
  type InputProps = {
5
5
  /**
6
- * used for the label's `for` attribute
6
+ * The value
7
7
  */
8
- id: string;
9
8
  value: string;
10
9
  /**
11
10
  * @default 'text'
@@ -17,19 +16,20 @@ type InputProps = {
17
16
  * That could be enforced through a union type but that seems a bit overkill
18
17
  * @default noop
19
18
  */
20
- onChange?: (text: string) => void;
19
+ onChangeText?: (text: string) => void;
20
+ onEditCompleted?: (text: string) => void;
21
21
  labelClassName?: string;
22
22
  initialState?: 'editing' | 'display';
23
23
  size?: number;
24
24
  disclaimer?: string;
25
- onEditCompleted?: (text: string) => void;
26
- } & Omit<InputHTMLAttributes<HTMLInputElement>, 'id' | 'value' | 'label' | 'type' | 'onChange' | 'crossOrigin'>;
25
+ } & Omit<InputHTMLAttributes<HTMLInputElement>, 'value' | 'label' | 'type' | 'crossOrigin'>;
27
26
  /**
28
27
  * A Text input component for inputting text. It changes appearance upon entering the edit mode and switches
29
28
  * back to display mode on loss of focus or on enter
30
29
  *
31
30
  * The State is managed by the parent
32
31
  */
33
- declare const ToggleableInput: ({ id, type, value, onChange, labelClassName, initialState, size, disclaimer, onBlur, onEditCompleted, ...restProps }: InputProps) => react_jsx_runtime.JSX.Element;
32
+ declare const ToggleableInput: ({ type, value, onChange, onChangeText, onEditCompleted, labelClassName, initialState, size, disclaimer, onBlur, ...restProps }: InputProps) => react_jsx_runtime.JSX.Element;
33
+ declare const ToggleableInputUncontrolled: ({ value: initialValue, onChangeText, ...restProps }: InputProps) => react_jsx_runtime.JSX.Element;
34
34
 
35
- export { ToggleableInput };
35
+ export { ToggleableInput, ToggleableInputUncontrolled };
@@ -30,7 +30,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/components/user-input/ToggleableInput.tsx
31
31
  var ToggleableInput_exports = {};
32
32
  __export(ToggleableInput_exports, {
33
- ToggleableInput: () => ToggleableInput
33
+ ToggleableInput: () => ToggleableInput,
34
+ ToggleableInputUncontrolled: () => ToggleableInputUncontrolled
34
35
  });
35
36
  module.exports = __toCommonJS(ToggleableInput_exports);
36
37
  var import_react2 = require("react");
@@ -83,24 +84,30 @@ var noop = () => void 0;
83
84
  // src/components/user-input/ToggleableInput.tsx
84
85
  var import_jsx_runtime = require("react/jsx-runtime");
85
86
  var ToggleableInput = ({
86
- id,
87
87
  type = "text",
88
88
  value,
89
89
  onChange = noop,
90
+ onChangeText = noop,
91
+ onEditCompleted = noop,
90
92
  labelClassName = "",
91
93
  initialState = "display",
92
94
  size = 20,
93
95
  disclaimer,
94
96
  onBlur,
95
- onEditCompleted = noop,
96
97
  ...restProps
97
98
  }) => {
98
99
  const [isEditing, setIsEditing] = (0, import_react2.useState)(initialState !== "display");
99
100
  const { restartTimer, clearUpdateTimer } = useSaveDelay(() => void 0, 3e3);
101
+ const ref = (0, import_react2.useRef)(null);
100
102
  const onEditCompletedWrapper = (text) => {
101
103
  onEditCompleted(text);
102
104
  clearUpdateTimer();
103
105
  };
106
+ (0, import_react2.useEffect)(() => {
107
+ if (isEditing) {
108
+ ref.current?.focus();
109
+ }
110
+ }, [isEditing]);
104
111
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
105
112
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
106
113
  "div",
@@ -111,17 +118,17 @@ var ToggleableInput = ({
111
118
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: (0, import_clsx.default)("row overflow-hidden", { "flex-1": isEditing }), children: isEditing ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
112
119
  "input",
113
120
  {
114
- autoFocus: true,
121
+ ref,
115
122
  ...restProps,
116
123
  value,
117
124
  type,
118
- id,
119
125
  onChange: (event) => {
120
126
  const value2 = event.target.value;
121
127
  restartTimer(() => {
122
128
  onEditCompletedWrapper(value2);
123
129
  });
124
- onChange(value2);
130
+ onChangeText(value2);
131
+ onChange(event);
125
132
  },
126
133
  onBlur: (event) => {
127
134
  if (onBlur) {
@@ -136,7 +143,7 @@ var ToggleableInput = ({
136
143
  onEditCompletedWrapper(value);
137
144
  }
138
145
  },
139
- className: (0, import_clsx.default)(labelClassName, `w-full border-none rounded-none focus:ring-0 shadow-transparent decoration-primary p-0 underline-offset-4`, {
146
+ className: (0, import_clsx.default)(labelClassName, `w-full border-none rounded-none ring-0 outline-0 shadow-transparent decoration-primary p-0 underline-offset-4`, {
140
147
  underline: isEditing
141
148
  }),
142
149
  onFocus: (event) => event.target.select()
@@ -148,15 +155,44 @@ var ToggleableInput = ({
148
155
  children: value
149
156
  }
150
157
  ) }),
151
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Pencil, { className: (0, import_clsx.default)(`min-w-[${size}px] cursor-pointer`, { "text-transparent": isEditing }), size })
158
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
159
+ import_lucide_react.Pencil,
160
+ {
161
+ className: (0, import_clsx.default)(`cursor-pointer`, { "text-transparent": isEditing }),
162
+ size,
163
+ style: { minWidth: `${size}px` }
164
+ }
165
+ )
152
166
  ]
153
167
  }
154
168
  ),
155
169
  isEditing && disclaimer && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: "text-negative", children: disclaimer })
156
170
  ] });
157
171
  };
172
+ var ToggleableInputUncontrolled = ({
173
+ value: initialValue,
174
+ onChangeText = noop,
175
+ ...restProps
176
+ }) => {
177
+ const [value, setValue] = (0, import_react2.useState)(initialValue);
178
+ (0, import_react2.useEffect)(() => {
179
+ setValue(initialValue);
180
+ }, [initialValue]);
181
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
182
+ ToggleableInput,
183
+ {
184
+ value,
185
+ onChangeText: (text) => {
186
+ setValue(text);
187
+ onChangeText(text);
188
+ },
189
+ ...restProps
190
+ }
191
+ );
192
+ };
158
193
  // Annotate the CommonJS export names for ESM import in node:
159
194
  0 && (module.exports = {
160
- ToggleableInput
195
+ ToggleableInput,
196
+ ToggleableInputUncontrolled
161
197
  });
162
198
  //# sourceMappingURL=ToggleableInput.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/user-input/ToggleableInput.tsx","../../../src/hooks/useSaveDelay.ts","../../../src/util/noop.ts"],"sourcesContent":["import { useState } from 'react'\nimport type { HTMLInputTypeAttribute, InputHTMLAttributes } from 'react'\nimport { Pencil } from 'lucide-react'\nimport clsx from 'clsx'\nimport { useSaveDelay } from '../../hooks/useSaveDelay'\nimport { noop } from '../../util/noop'\n\ntype InputProps = {\n /**\n * used for the label's `for` attribute\n */\n id: string,\n value: string,\n /**\n * @default 'text'\n */\n type?: HTMLInputTypeAttribute,\n /**\n * Callback for when the input's value changes\n * This is pretty much required but made optional for the rare cases where it actually isn't need such as when used with disabled\n * That could be enforced through a union type but that seems a bit overkill\n * @default noop\n */\n onChange?: (text: string) => void,\n labelClassName?: string,\n initialState?: 'editing' | 'display',\n size?: number,\n disclaimer?: string,\n onEditCompleted?: (text: string) => void,\n} & Omit<InputHTMLAttributes<HTMLInputElement>, 'id' | 'value' | 'label' | 'type' | 'onChange' | 'crossOrigin'>\n\n/**\n * A Text input component for inputting text. It changes appearance upon entering the edit mode and switches\n * back to display mode on loss of focus or on enter\n *\n * The State is managed by the parent\n */\nexport const ToggleableInput = ({\n id,\n type = 'text',\n value,\n onChange = noop,\n labelClassName = '',\n initialState = 'display',\n size = 20,\n disclaimer,\n onBlur,\n onEditCompleted = noop,\n ...restProps\n}: InputProps) => {\n const [isEditing, setIsEditing] = useState(initialState !== 'display')\n const { restartTimer, clearUpdateTimer } = useSaveDelay(() => undefined, 3000)\n\n const onEditCompletedWrapper = (text: string) => {\n onEditCompleted(text)\n clearUpdateTimer()\n }\n\n return (\n <div>\n <div\n className=\"row items-center w-full gap-x-2 overflow-hidden\"\n onClick={() => !isEditing ? setIsEditing(!isEditing) : undefined}\n >\n <div className={clsx('row overflow-hidden', { 'flex-1': isEditing })}>\n {isEditing ? (\n <input\n autoFocus\n {...restProps}\n value={value}\n type={type}\n id={id}\n onChange={event => {\n const value = event.target.value\n restartTimer(() => {\n onEditCompletedWrapper(value)\n })\n onChange(value)\n }}\n onBlur={(event) => {\n if (onBlur) {\n onBlur(event)\n }\n onEditCompletedWrapper(value)\n setIsEditing(false)\n }}\n onKeyDown={event => {\n if (event.key === 'Enter') {\n setIsEditing(false)\n onEditCompletedWrapper(value)\n }\n }}\n className={clsx(labelClassName, `w-full border-none rounded-none focus:ring-0 shadow-transparent decoration-primary p-0 underline-offset-4`, {\n underline: isEditing\n })}\n onFocus={event => event.target.select()}\n />\n ) : (\n <span\n className={clsx(labelClassName, 'max-w-xs break-words overflow-hidden')}\n >\n {value}\n </span>\n )}\n </div>\n <Pencil className={clsx(`min-w-[${size}px] cursor-pointer`, { 'text-transparent': isEditing })} size={size} />\n </div>\n {(isEditing && disclaimer) && (\n <label className=\"text-negative\">\n {disclaimer}\n </label>\n )}\n </div>\n )\n}\n","import { useEffect, useState } from 'react'\n\nexport function useSaveDelay(setNotificationStatus: (isShowing: boolean) => void, delay: number) {\n const [updateTimer, setUpdateTimer] = useState<NodeJS.Timeout | undefined>(undefined)\n const [notificationTimer, setNotificationTimer] = useState<NodeJS.Timeout | undefined>(undefined)\n\n const restartTimer = (onSave: () => void) => {\n clearTimeout(updateTimer)\n setUpdateTimer(setTimeout(() => {\n onSave()\n setNotificationStatus(true)\n // Show Saved Notification for fade animation duration\n clearTimeout(notificationTimer)\n setNotificationTimer(setTimeout(() => {\n setNotificationStatus(false)\n clearTimeout(notificationTimer)\n }, delay))\n clearTimeout(updateTimer)\n }, delay))\n }\n\n const clearUpdateTimer = (hasSaved = true) => {\n clearTimeout(updateTimer)\n if (hasSaved) {\n setNotificationStatus(true)\n clearTimeout(notificationTimer)\n setNotificationTimer(setTimeout(() => {\n setNotificationStatus(false)\n clearTimeout(notificationTimer)\n }, delay))\n } else {\n setNotificationStatus(false)\n }\n }\n\n useEffect(() => {\n return () => {\n clearTimeout(updateTimer)\n clearTimeout(notificationTimer)\n }\n }, []) // eslint-disable-line react-hooks/exhaustive-deps\n\n return { restartTimer, clearUpdateTimer }\n}","export const noop = () => undefined\n"],"mappings":"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","names":["import_react","clsx","value"]}
1
+ {"version":3,"sources":["../../../src/components/user-input/ToggleableInput.tsx","../../../src/hooks/useSaveDelay.ts","../../../src/util/noop.ts"],"sourcesContent":["import type { HTMLInputTypeAttribute, InputHTMLAttributes } from 'react'\nimport { useEffect, useRef, useState } from 'react'\nimport { Pencil } from 'lucide-react'\nimport clsx from 'clsx'\nimport { useSaveDelay } from '../../hooks/useSaveDelay'\nimport { noop } from '../../util/noop'\n\ntype InputProps = {\n /**\n * The value\n */\n value: string,\n /**\n * @default 'text'\n */\n type?: HTMLInputTypeAttribute,\n /**\n * Callback for when the input's value changes\n * This is pretty much required but made optional for the rare cases where it actually isn't need such as when used with disabled\n * That could be enforced through a union type but that seems a bit overkill\n * @default noop\n */\n onChangeText?: (text: string) => void,\n onEditCompleted?: (text: string) => void,\n labelClassName?: string,\n initialState?: 'editing' | 'display',\n size?: number,\n disclaimer?: string,\n} & Omit<InputHTMLAttributes<HTMLInputElement>, 'value' | 'label' | 'type' | 'crossOrigin'>\n\n/**\n * A Text input component for inputting text. It changes appearance upon entering the edit mode and switches\n * back to display mode on loss of focus or on enter\n *\n * The State is managed by the parent\n */\nexport const ToggleableInput = ({\n type = 'text',\n value,\n onChange = noop,\n onChangeText = noop,\n onEditCompleted = noop,\n labelClassName = '',\n initialState = 'display',\n size = 20,\n disclaimer,\n onBlur,\n ...restProps\n }: InputProps) => {\n const [isEditing, setIsEditing] = useState(initialState !== 'display')\n const { restartTimer, clearUpdateTimer } = useSaveDelay(() => undefined, 3000)\n const ref = useRef<HTMLInputElement>(null)\n\n const onEditCompletedWrapper = (text: string) => {\n onEditCompleted(text)\n clearUpdateTimer()\n }\n\n useEffect(() => {\n if (isEditing) {\n ref.current?.focus()\n }\n }, [isEditing])\n\n return (\n <div>\n <div\n className=\"row items-center w-full gap-x-2 overflow-hidden\"\n onClick={() => !isEditing ? setIsEditing(!isEditing) : undefined}\n >\n <div className={clsx('row overflow-hidden', { 'flex-1': isEditing })}>\n {isEditing ? (\n <input\n ref={ref}\n {...restProps}\n value={value}\n type={type}\n onChange={event => {\n const value = event.target.value\n restartTimer(() => {\n onEditCompletedWrapper(value)\n })\n onChangeText(value)\n onChange(event)\n }}\n onBlur={(event) => {\n if (onBlur) {\n onBlur(event)\n }\n onEditCompletedWrapper(value)\n setIsEditing(false)\n }}\n onKeyDown={event => {\n if (event.key === 'Enter') {\n setIsEditing(false)\n onEditCompletedWrapper(value)\n }\n }}\n className={clsx(labelClassName, `w-full border-none rounded-none ring-0 outline-0 shadow-transparent decoration-primary p-0 underline-offset-4`, {\n underline: isEditing\n })}\n onFocus={event => event.target.select()}\n />\n ) : (\n <span\n className={clsx(labelClassName, 'max-w-xs break-words overflow-hidden')}\n >\n {value}\n </span>\n )}\n </div>\n <Pencil\n className={clsx(`cursor-pointer`, { 'text-transparent': isEditing })}\n size={size}\n style={{ minWidth: `${size}px` }}\n />\n </div>\n {(isEditing && disclaimer) && (\n <label className=\"text-negative\">\n {disclaimer}\n </label>\n )}\n </div>\n )\n}\n\nexport const ToggleableInputUncontrolled = ({\n value: initialValue,\n onChangeText = noop,\n ...restProps\n }: InputProps) => {\n const [value, setValue] = useState(initialValue)\n\n useEffect(() => {\n setValue(initialValue)\n }, [initialValue])\n\n return (\n <ToggleableInput\n value={value}\n onChangeText={text => {\n setValue(text)\n onChangeText(text)\n }}\n {...restProps}\n />\n )\n}\n","import { useEffect, useState } from 'react'\n\nexport function useSaveDelay(setNotificationStatus: (isShowing: boolean) => void, delay: number) {\n const [updateTimer, setUpdateTimer] = useState<NodeJS.Timeout | undefined>(undefined)\n const [notificationTimer, setNotificationTimer] = useState<NodeJS.Timeout | undefined>(undefined)\n\n const restartTimer = (onSave: () => void) => {\n clearTimeout(updateTimer)\n setUpdateTimer(setTimeout(() => {\n onSave()\n setNotificationStatus(true)\n // Show Saved Notification for fade animation duration\n clearTimeout(notificationTimer)\n setNotificationTimer(setTimeout(() => {\n setNotificationStatus(false)\n clearTimeout(notificationTimer)\n }, delay))\n clearTimeout(updateTimer)\n }, delay))\n }\n\n const clearUpdateTimer = (hasSaved = true) => {\n clearTimeout(updateTimer)\n if (hasSaved) {\n setNotificationStatus(true)\n clearTimeout(notificationTimer)\n setNotificationTimer(setTimeout(() => {\n setNotificationStatus(false)\n clearTimeout(notificationTimer)\n }, delay))\n } else {\n setNotificationStatus(false)\n }\n }\n\n useEffect(() => {\n return () => {\n clearTimeout(updateTimer)\n clearTimeout(notificationTimer)\n }\n }, []) // eslint-disable-line react-hooks/exhaustive-deps\n\n return { restartTimer, clearUpdateTimer }\n}","export const noop = () => undefined\n"],"mappings":"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","names":["import_react","clsx","value"]}
@@ -1,5 +1,5 @@
1
1
  // src/components/user-input/ToggleableInput.tsx
2
- import { useState as useState2 } from "react";
2
+ import { useEffect as useEffect2, useRef, useState as useState2 } from "react";
3
3
  import { Pencil } from "lucide-react";
4
4
  import clsx from "clsx";
5
5
 
@@ -49,24 +49,30 @@ var noop = () => void 0;
49
49
  // src/components/user-input/ToggleableInput.tsx
50
50
  import { jsx, jsxs } from "react/jsx-runtime";
51
51
  var ToggleableInput = ({
52
- id,
53
52
  type = "text",
54
53
  value,
55
54
  onChange = noop,
55
+ onChangeText = noop,
56
+ onEditCompleted = noop,
56
57
  labelClassName = "",
57
58
  initialState = "display",
58
59
  size = 20,
59
60
  disclaimer,
60
61
  onBlur,
61
- onEditCompleted = noop,
62
62
  ...restProps
63
63
  }) => {
64
64
  const [isEditing, setIsEditing] = useState2(initialState !== "display");
65
65
  const { restartTimer, clearUpdateTimer } = useSaveDelay(() => void 0, 3e3);
66
+ const ref = useRef(null);
66
67
  const onEditCompletedWrapper = (text) => {
67
68
  onEditCompleted(text);
68
69
  clearUpdateTimer();
69
70
  };
71
+ useEffect2(() => {
72
+ if (isEditing) {
73
+ ref.current?.focus();
74
+ }
75
+ }, [isEditing]);
70
76
  return /* @__PURE__ */ jsxs("div", { children: [
71
77
  /* @__PURE__ */ jsxs(
72
78
  "div",
@@ -77,17 +83,17 @@ var ToggleableInput = ({
77
83
  /* @__PURE__ */ jsx("div", { className: clsx("row overflow-hidden", { "flex-1": isEditing }), children: isEditing ? /* @__PURE__ */ jsx(
78
84
  "input",
79
85
  {
80
- autoFocus: true,
86
+ ref,
81
87
  ...restProps,
82
88
  value,
83
89
  type,
84
- id,
85
90
  onChange: (event) => {
86
91
  const value2 = event.target.value;
87
92
  restartTimer(() => {
88
93
  onEditCompletedWrapper(value2);
89
94
  });
90
- onChange(value2);
95
+ onChangeText(value2);
96
+ onChange(event);
91
97
  },
92
98
  onBlur: (event) => {
93
99
  if (onBlur) {
@@ -102,7 +108,7 @@ var ToggleableInput = ({
102
108
  onEditCompletedWrapper(value);
103
109
  }
104
110
  },
105
- className: clsx(labelClassName, `w-full border-none rounded-none focus:ring-0 shadow-transparent decoration-primary p-0 underline-offset-4`, {
111
+ className: clsx(labelClassName, `w-full border-none rounded-none ring-0 outline-0 shadow-transparent decoration-primary p-0 underline-offset-4`, {
106
112
  underline: isEditing
107
113
  }),
108
114
  onFocus: (event) => event.target.select()
@@ -114,14 +120,43 @@ var ToggleableInput = ({
114
120
  children: value
115
121
  }
116
122
  ) }),
117
- /* @__PURE__ */ jsx(Pencil, { className: clsx(`min-w-[${size}px] cursor-pointer`, { "text-transparent": isEditing }), size })
123
+ /* @__PURE__ */ jsx(
124
+ Pencil,
125
+ {
126
+ className: clsx(`cursor-pointer`, { "text-transparent": isEditing }),
127
+ size,
128
+ style: { minWidth: `${size}px` }
129
+ }
130
+ )
118
131
  ]
119
132
  }
120
133
  ),
121
134
  isEditing && disclaimer && /* @__PURE__ */ jsx("label", { className: "text-negative", children: disclaimer })
122
135
  ] });
123
136
  };
137
+ var ToggleableInputUncontrolled = ({
138
+ value: initialValue,
139
+ onChangeText = noop,
140
+ ...restProps
141
+ }) => {
142
+ const [value, setValue] = useState2(initialValue);
143
+ useEffect2(() => {
144
+ setValue(initialValue);
145
+ }, [initialValue]);
146
+ return /* @__PURE__ */ jsx(
147
+ ToggleableInput,
148
+ {
149
+ value,
150
+ onChangeText: (text) => {
151
+ setValue(text);
152
+ onChangeText(text);
153
+ },
154
+ ...restProps
155
+ }
156
+ );
157
+ };
124
158
  export {
125
- ToggleableInput
159
+ ToggleableInput,
160
+ ToggleableInputUncontrolled
126
161
  };
127
162
  //# sourceMappingURL=ToggleableInput.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/user-input/ToggleableInput.tsx","../../../src/hooks/useSaveDelay.ts","../../../src/util/noop.ts"],"sourcesContent":["import { useState } from 'react'\nimport type { HTMLInputTypeAttribute, InputHTMLAttributes } from 'react'\nimport { Pencil } from 'lucide-react'\nimport clsx from 'clsx'\nimport { useSaveDelay } from '../../hooks/useSaveDelay'\nimport { noop } from '../../util/noop'\n\ntype InputProps = {\n /**\n * used for the label's `for` attribute\n */\n id: string,\n value: string,\n /**\n * @default 'text'\n */\n type?: HTMLInputTypeAttribute,\n /**\n * Callback for when the input's value changes\n * This is pretty much required but made optional for the rare cases where it actually isn't need such as when used with disabled\n * That could be enforced through a union type but that seems a bit overkill\n * @default noop\n */\n onChange?: (text: string) => void,\n labelClassName?: string,\n initialState?: 'editing' | 'display',\n size?: number,\n disclaimer?: string,\n onEditCompleted?: (text: string) => void,\n} & Omit<InputHTMLAttributes<HTMLInputElement>, 'id' | 'value' | 'label' | 'type' | 'onChange' | 'crossOrigin'>\n\n/**\n * A Text input component for inputting text. It changes appearance upon entering the edit mode and switches\n * back to display mode on loss of focus or on enter\n *\n * The State is managed by the parent\n */\nexport const ToggleableInput = ({\n id,\n type = 'text',\n value,\n onChange = noop,\n labelClassName = '',\n initialState = 'display',\n size = 20,\n disclaimer,\n onBlur,\n onEditCompleted = noop,\n ...restProps\n}: InputProps) => {\n const [isEditing, setIsEditing] = useState(initialState !== 'display')\n const { restartTimer, clearUpdateTimer } = useSaveDelay(() => undefined, 3000)\n\n const onEditCompletedWrapper = (text: string) => {\n onEditCompleted(text)\n clearUpdateTimer()\n }\n\n return (\n <div>\n <div\n className=\"row items-center w-full gap-x-2 overflow-hidden\"\n onClick={() => !isEditing ? setIsEditing(!isEditing) : undefined}\n >\n <div className={clsx('row overflow-hidden', { 'flex-1': isEditing })}>\n {isEditing ? (\n <input\n autoFocus\n {...restProps}\n value={value}\n type={type}\n id={id}\n onChange={event => {\n const value = event.target.value\n restartTimer(() => {\n onEditCompletedWrapper(value)\n })\n onChange(value)\n }}\n onBlur={(event) => {\n if (onBlur) {\n onBlur(event)\n }\n onEditCompletedWrapper(value)\n setIsEditing(false)\n }}\n onKeyDown={event => {\n if (event.key === 'Enter') {\n setIsEditing(false)\n onEditCompletedWrapper(value)\n }\n }}\n className={clsx(labelClassName, `w-full border-none rounded-none focus:ring-0 shadow-transparent decoration-primary p-0 underline-offset-4`, {\n underline: isEditing\n })}\n onFocus={event => event.target.select()}\n />\n ) : (\n <span\n className={clsx(labelClassName, 'max-w-xs break-words overflow-hidden')}\n >\n {value}\n </span>\n )}\n </div>\n <Pencil className={clsx(`min-w-[${size}px] cursor-pointer`, { 'text-transparent': isEditing })} size={size} />\n </div>\n {(isEditing && disclaimer) && (\n <label className=\"text-negative\">\n {disclaimer}\n </label>\n )}\n </div>\n )\n}\n","import { useEffect, useState } from 'react'\n\nexport function useSaveDelay(setNotificationStatus: (isShowing: boolean) => void, delay: number) {\n const [updateTimer, setUpdateTimer] = useState<NodeJS.Timeout | undefined>(undefined)\n const [notificationTimer, setNotificationTimer] = useState<NodeJS.Timeout | undefined>(undefined)\n\n const restartTimer = (onSave: () => void) => {\n clearTimeout(updateTimer)\n setUpdateTimer(setTimeout(() => {\n onSave()\n setNotificationStatus(true)\n // Show Saved Notification for fade animation duration\n clearTimeout(notificationTimer)\n setNotificationTimer(setTimeout(() => {\n setNotificationStatus(false)\n clearTimeout(notificationTimer)\n }, delay))\n clearTimeout(updateTimer)\n }, delay))\n }\n\n const clearUpdateTimer = (hasSaved = true) => {\n clearTimeout(updateTimer)\n if (hasSaved) {\n setNotificationStatus(true)\n clearTimeout(notificationTimer)\n setNotificationTimer(setTimeout(() => {\n setNotificationStatus(false)\n clearTimeout(notificationTimer)\n }, delay))\n } else {\n setNotificationStatus(false)\n }\n }\n\n useEffect(() => {\n return () => {\n clearTimeout(updateTimer)\n clearTimeout(notificationTimer)\n }\n }, []) // eslint-disable-line react-hooks/exhaustive-deps\n\n return { restartTimer, clearUpdateTimer }\n}","export const noop = () => undefined\n"],"mappings":"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","names":["useState","useState","value"]}
1
+ {"version":3,"sources":["../../../src/components/user-input/ToggleableInput.tsx","../../../src/hooks/useSaveDelay.ts","../../../src/util/noop.ts"],"sourcesContent":["import type { HTMLInputTypeAttribute, InputHTMLAttributes } from 'react'\nimport { useEffect, useRef, useState } from 'react'\nimport { Pencil } from 'lucide-react'\nimport clsx from 'clsx'\nimport { useSaveDelay } from '../../hooks/useSaveDelay'\nimport { noop } from '../../util/noop'\n\ntype InputProps = {\n /**\n * The value\n */\n value: string,\n /**\n * @default 'text'\n */\n type?: HTMLInputTypeAttribute,\n /**\n * Callback for when the input's value changes\n * This is pretty much required but made optional for the rare cases where it actually isn't need such as when used with disabled\n * That could be enforced through a union type but that seems a bit overkill\n * @default noop\n */\n onChangeText?: (text: string) => void,\n onEditCompleted?: (text: string) => void,\n labelClassName?: string,\n initialState?: 'editing' | 'display',\n size?: number,\n disclaimer?: string,\n} & Omit<InputHTMLAttributes<HTMLInputElement>, 'value' | 'label' | 'type' | 'crossOrigin'>\n\n/**\n * A Text input component for inputting text. It changes appearance upon entering the edit mode and switches\n * back to display mode on loss of focus or on enter\n *\n * The State is managed by the parent\n */\nexport const ToggleableInput = ({\n type = 'text',\n value,\n onChange = noop,\n onChangeText = noop,\n onEditCompleted = noop,\n labelClassName = '',\n initialState = 'display',\n size = 20,\n disclaimer,\n onBlur,\n ...restProps\n }: InputProps) => {\n const [isEditing, setIsEditing] = useState(initialState !== 'display')\n const { restartTimer, clearUpdateTimer } = useSaveDelay(() => undefined, 3000)\n const ref = useRef<HTMLInputElement>(null)\n\n const onEditCompletedWrapper = (text: string) => {\n onEditCompleted(text)\n clearUpdateTimer()\n }\n\n useEffect(() => {\n if (isEditing) {\n ref.current?.focus()\n }\n }, [isEditing])\n\n return (\n <div>\n <div\n className=\"row items-center w-full gap-x-2 overflow-hidden\"\n onClick={() => !isEditing ? setIsEditing(!isEditing) : undefined}\n >\n <div className={clsx('row overflow-hidden', { 'flex-1': isEditing })}>\n {isEditing ? (\n <input\n ref={ref}\n {...restProps}\n value={value}\n type={type}\n onChange={event => {\n const value = event.target.value\n restartTimer(() => {\n onEditCompletedWrapper(value)\n })\n onChangeText(value)\n onChange(event)\n }}\n onBlur={(event) => {\n if (onBlur) {\n onBlur(event)\n }\n onEditCompletedWrapper(value)\n setIsEditing(false)\n }}\n onKeyDown={event => {\n if (event.key === 'Enter') {\n setIsEditing(false)\n onEditCompletedWrapper(value)\n }\n }}\n className={clsx(labelClassName, `w-full border-none rounded-none ring-0 outline-0 shadow-transparent decoration-primary p-0 underline-offset-4`, {\n underline: isEditing\n })}\n onFocus={event => event.target.select()}\n />\n ) : (\n <span\n className={clsx(labelClassName, 'max-w-xs break-words overflow-hidden')}\n >\n {value}\n </span>\n )}\n </div>\n <Pencil\n className={clsx(`cursor-pointer`, { 'text-transparent': isEditing })}\n size={size}\n style={{ minWidth: `${size}px` }}\n />\n </div>\n {(isEditing && disclaimer) && (\n <label className=\"text-negative\">\n {disclaimer}\n </label>\n )}\n </div>\n )\n}\n\nexport const ToggleableInputUncontrolled = ({\n value: initialValue,\n onChangeText = noop,\n ...restProps\n }: InputProps) => {\n const [value, setValue] = useState(initialValue)\n\n useEffect(() => {\n setValue(initialValue)\n }, [initialValue])\n\n return (\n <ToggleableInput\n value={value}\n onChangeText={text => {\n setValue(text)\n onChangeText(text)\n }}\n {...restProps}\n />\n )\n}\n","import { useEffect, useState } from 'react'\n\nexport function useSaveDelay(setNotificationStatus: (isShowing: boolean) => void, delay: number) {\n const [updateTimer, setUpdateTimer] = useState<NodeJS.Timeout | undefined>(undefined)\n const [notificationTimer, setNotificationTimer] = useState<NodeJS.Timeout | undefined>(undefined)\n\n const restartTimer = (onSave: () => void) => {\n clearTimeout(updateTimer)\n setUpdateTimer(setTimeout(() => {\n onSave()\n setNotificationStatus(true)\n // Show Saved Notification for fade animation duration\n clearTimeout(notificationTimer)\n setNotificationTimer(setTimeout(() => {\n setNotificationStatus(false)\n clearTimeout(notificationTimer)\n }, delay))\n clearTimeout(updateTimer)\n }, delay))\n }\n\n const clearUpdateTimer = (hasSaved = true) => {\n clearTimeout(updateTimer)\n if (hasSaved) {\n setNotificationStatus(true)\n clearTimeout(notificationTimer)\n setNotificationTimer(setTimeout(() => {\n setNotificationStatus(false)\n clearTimeout(notificationTimer)\n }, delay))\n } else {\n setNotificationStatus(false)\n }\n }\n\n useEffect(() => {\n return () => {\n clearTimeout(updateTimer)\n clearTimeout(notificationTimer)\n }\n }, []) // eslint-disable-line react-hooks/exhaustive-deps\n\n return { restartTimer, clearUpdateTimer }\n}","export const noop = () => undefined\n"],"mappings":"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","names":["useEffect","useState","useState","useEffect","value"]}
@@ -1538,6 +1538,10 @@
1538
1538
  --tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
1539
1539
  box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
1540
1540
  }
1541
+ .ring-0 {
1542
+ --tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
1543
+ box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
1544
+ }
1541
1545
  .ring-1 {
1542
1546
  --tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
1543
1547
  box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
@@ -1562,6 +1566,10 @@
1562
1566
  outline-style: var(--tw-outline-style);
1563
1567
  outline-width: 1px;
1564
1568
  }
1569
+ .outline-0 {
1570
+ outline-style: var(--tw-outline-style);
1571
+ outline-width: 0px;
1572
+ }
1565
1573
  .outline-primary {
1566
1574
  outline-color: var(--color-primary);
1567
1575
  }
package/dist/index.d.mts CHANGED
@@ -61,7 +61,7 @@ export { ScrollPicker, ScrollPickerProps } from './components/user-input/ScrollP
61
61
  export { SearchableSelect, SearchableSelectProps } from './components/user-input/SearchableSelect.mjs';
62
62
  export { Select, SelectOption, SelectProps } from './components/user-input/Select.mjs';
63
63
  export { Textarea, TextareaProps } from './components/user-input/Textarea.mjs';
64
- export { ToggleableInput } from './components/user-input/ToggleableInput.mjs';
64
+ export { ToggleableInput, ToggleableInputUncontrolled } from './components/user-input/ToggleableInput.mjs';
65
65
  export { useHoverState } from './hooks/useHoverState.mjs';
66
66
  export { DEFAULT_LANGUAGE, LanguageContext, LanguageContextValue, Languages, ProvideLanguage, languages, languagesLocalNames, useLanguage, useLocale } from './hooks/useLanguage.mjs';
67
67
  export { useLocalStorage } from './hooks/useLocalStorage.mjs';
package/dist/index.d.ts CHANGED
@@ -61,7 +61,7 @@ export { ScrollPicker, ScrollPickerProps } from './components/user-input/ScrollP
61
61
  export { SearchableSelect, SearchableSelectProps } from './components/user-input/SearchableSelect.js';
62
62
  export { Select, SelectOption, SelectProps } from './components/user-input/Select.js';
63
63
  export { Textarea, TextareaProps } from './components/user-input/Textarea.js';
64
- export { ToggleableInput } from './components/user-input/ToggleableInput.js';
64
+ export { ToggleableInput, ToggleableInputUncontrolled } from './components/user-input/ToggleableInput.js';
65
65
  export { useHoverState } from './hooks/useHoverState.js';
66
66
  export { DEFAULT_LANGUAGE, LanguageContext, LanguageContextValue, Languages, ProvideLanguage, languages, languagesLocalNames, useLanguage, useLocale } from './hooks/useLanguage.js';
67
67
  export { useLocalStorage } from './hooks/useLocalStorage.js';
package/dist/index.js CHANGED
@@ -120,6 +120,7 @@ __export(index_exports, {
120
120
  TimeDisplay: () => TimeDisplay,
121
121
  TimePicker: () => TimePicker,
122
122
  ToggleableInput: () => ToggleableInput,
123
+ ToggleableInputUncontrolled: () => ToggleableInputUncontrolled,
123
124
  Tooltip: () => Tooltip,
124
125
  UncontrolledCheckbox: () => UncontrolledCheckbox,
125
126
  UncontrolledInput: () => UncontrolledInput,
@@ -5422,24 +5423,30 @@ var import_lucide_react25 = require("lucide-react");
5422
5423
  var import_clsx45 = __toESM(require("clsx"));
5423
5424
  var import_jsx_runtime63 = require("react/jsx-runtime");
5424
5425
  var ToggleableInput = ({
5425
- id,
5426
5426
  type = "text",
5427
5427
  value,
5428
5428
  onChange = noop,
5429
+ onChangeText = noop,
5430
+ onEditCompleted = noop,
5429
5431
  labelClassName = "",
5430
5432
  initialState = "display",
5431
5433
  size = 20,
5432
5434
  disclaimer,
5433
5435
  onBlur,
5434
- onEditCompleted = noop,
5435
5436
  ...restProps
5436
5437
  }) => {
5437
5438
  const [isEditing, setIsEditing] = (0, import_react29.useState)(initialState !== "display");
5438
5439
  const { restartTimer, clearUpdateTimer } = useSaveDelay(() => void 0, 3e3);
5440
+ const ref = (0, import_react29.useRef)(null);
5439
5441
  const onEditCompletedWrapper = (text) => {
5440
5442
  onEditCompleted(text);
5441
5443
  clearUpdateTimer();
5442
5444
  };
5445
+ (0, import_react29.useEffect)(() => {
5446
+ if (isEditing) {
5447
+ ref.current?.focus();
5448
+ }
5449
+ }, [isEditing]);
5443
5450
  return /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { children: [
5444
5451
  /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(
5445
5452
  "div",
@@ -5450,17 +5457,17 @@ var ToggleableInput = ({
5450
5457
  /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("div", { className: (0, import_clsx45.default)("row overflow-hidden", { "flex-1": isEditing }), children: isEditing ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
5451
5458
  "input",
5452
5459
  {
5453
- autoFocus: true,
5460
+ ref,
5454
5461
  ...restProps,
5455
5462
  value,
5456
5463
  type,
5457
- id,
5458
5464
  onChange: (event) => {
5459
5465
  const value2 = event.target.value;
5460
5466
  restartTimer(() => {
5461
5467
  onEditCompletedWrapper(value2);
5462
5468
  });
5463
- onChange(value2);
5469
+ onChangeText(value2);
5470
+ onChange(event);
5464
5471
  },
5465
5472
  onBlur: (event) => {
5466
5473
  if (onBlur) {
@@ -5475,7 +5482,7 @@ var ToggleableInput = ({
5475
5482
  onEditCompletedWrapper(value);
5476
5483
  }
5477
5484
  },
5478
- className: (0, import_clsx45.default)(labelClassName, `w-full border-none rounded-none focus:ring-0 shadow-transparent decoration-primary p-0 underline-offset-4`, {
5485
+ className: (0, import_clsx45.default)(labelClassName, `w-full border-none rounded-none ring-0 outline-0 shadow-transparent decoration-primary p-0 underline-offset-4`, {
5479
5486
  underline: isEditing
5480
5487
  }),
5481
5488
  onFocus: (event) => event.target.select()
@@ -5487,13 +5494,41 @@ var ToggleableInput = ({
5487
5494
  children: value
5488
5495
  }
5489
5496
  ) }),
5490
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(import_lucide_react25.Pencil, { className: (0, import_clsx45.default)(`min-w-[${size}px] cursor-pointer`, { "text-transparent": isEditing }), size })
5497
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
5498
+ import_lucide_react25.Pencil,
5499
+ {
5500
+ className: (0, import_clsx45.default)(`cursor-pointer`, { "text-transparent": isEditing }),
5501
+ size,
5502
+ style: { minWidth: `${size}px` }
5503
+ }
5504
+ )
5491
5505
  ]
5492
5506
  }
5493
5507
  ),
5494
5508
  isEditing && disclaimer && /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("label", { className: "text-negative", children: disclaimer })
5495
5509
  ] });
5496
5510
  };
5511
+ var ToggleableInputUncontrolled = ({
5512
+ value: initialValue,
5513
+ onChangeText = noop,
5514
+ ...restProps
5515
+ }) => {
5516
+ const [value, setValue] = (0, import_react29.useState)(initialValue);
5517
+ (0, import_react29.useEffect)(() => {
5518
+ setValue(initialValue);
5519
+ }, [initialValue]);
5520
+ return /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
5521
+ ToggleableInput,
5522
+ {
5523
+ value,
5524
+ onChangeText: (text) => {
5525
+ setValue(text);
5526
+ onChangeText(text);
5527
+ },
5528
+ ...restProps
5529
+ }
5530
+ );
5531
+ };
5497
5532
 
5498
5533
  // src/hooks/useTheme.tsx
5499
5534
  var import_react30 = require("react");
@@ -5659,6 +5694,7 @@ var filterNews = (localizedNews, requiredKeys) => {
5659
5694
  TimeDisplay,
5660
5695
  TimePicker,
5661
5696
  ToggleableInput,
5697
+ ToggleableInputUncontrolled,
5662
5698
  Tooltip,
5663
5699
  UncontrolledCheckbox,
5664
5700
  UncontrolledInput,