@radix-solid-js/password-toggle-field 0.1.0

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 ADDED
@@ -0,0 +1,333 @@
1
+ 'use strict';
2
+
3
+ var solidJs = require('solid-js');
4
+ var primitive = require('@radix-solid-js/primitive');
5
+ var composeRefs = require('@radix-solid-js/compose-refs');
6
+ var context = require('@radix-solid-js/context');
7
+ var id = require('@radix-solid-js/id');
8
+ var useControllableState = require('@radix-solid-js/use-controllable-state');
9
+ var primitiveComponent = require('@radix-solid-js/primitive-component');
10
+
11
+ // src/password-toggle-field.tsx
12
+ var PASSWORD_TOGGLE_FIELD_NAME = "PasswordToggleField";
13
+ var INITIAL_FOCUS_STATE = {
14
+ clickTriggered: false,
15
+ selectionStart: null,
16
+ selectionEnd: null
17
+ };
18
+ var [createPasswordToggleFieldContext, createPasswordToggleFieldScope] = context.createContextScope(PASSWORD_TOGGLE_FIELD_NAME);
19
+ var [PasswordToggleFieldProvider, usePasswordToggleFieldContext] = createPasswordToggleFieldContext(PASSWORD_TOGGLE_FIELD_NAME);
20
+ function PasswordToggleField(props) {
21
+ const [local] = solidJs.splitProps(props, [
22
+ "__scopePasswordToggleField",
23
+ "id",
24
+ "visible",
25
+ "defaultVisible",
26
+ "onVisibilityChange",
27
+ "children"
28
+ ]);
29
+ const baseId = id.createId(local.id);
30
+ const defaultInputId = `${baseId}-input`;
31
+ const [inputIdState, setInputIdState] = solidJs.createSignal(defaultInputId);
32
+ const inputId = () => inputIdState() ?? defaultInputId;
33
+ const syncInputId = (providedId) => {
34
+ setInputIdState(providedId != null ? String(providedId) : null);
35
+ };
36
+ const [visible, setVisible] = useControllableState.createControllableSignal({
37
+ prop: () => local.visible,
38
+ defaultProp: local.defaultVisible ?? false,
39
+ onChange: local.onVisibilityChange,
40
+ caller: PASSWORD_TOGGLE_FIELD_NAME
41
+ });
42
+ const [inputRef, setInputRef] = solidJs.createSignal(null);
43
+ const focusState = { ...INITIAL_FOCUS_STATE };
44
+ return /* @__PURE__ */ React.createElement(
45
+ PasswordToggleFieldProvider,
46
+ {
47
+ scope: local.__scopePasswordToggleField,
48
+ inputId,
49
+ inputRef,
50
+ setInputRef,
51
+ visible,
52
+ setVisible,
53
+ syncInputId,
54
+ focusState
55
+ },
56
+ local.children
57
+ );
58
+ }
59
+ var PASSWORD_TOGGLE_FIELD_INPUT_NAME = PASSWORD_TOGGLE_FIELD_NAME + "Input";
60
+ function PasswordToggleFieldInput(props) {
61
+ const [local, rest] = solidJs.splitProps(props, [
62
+ "__scopePasswordToggleField",
63
+ "autocomplete",
64
+ "autoCapitalize",
65
+ "spellcheck",
66
+ "id",
67
+ "ref",
68
+ "onBlur"
69
+ ]);
70
+ const context = usePasswordToggleFieldContext(
71
+ PASSWORD_TOGGLE_FIELD_INPUT_NAME,
72
+ local.__scopePasswordToggleField
73
+ );
74
+ solidJs.createEffect(() => {
75
+ context.syncInputId(local.id);
76
+ });
77
+ solidJs.createEffect(() => {
78
+ const inputElement = context.inputRef();
79
+ const form = inputElement?.form;
80
+ if (!form) return;
81
+ const controller = new AbortController();
82
+ form.addEventListener(
83
+ "reset",
84
+ (event) => {
85
+ if (!event.defaultPrevented) {
86
+ context.setVisible(false);
87
+ }
88
+ },
89
+ { signal: controller.signal }
90
+ );
91
+ form.addEventListener(
92
+ "submit",
93
+ () => {
94
+ context.setVisible(false);
95
+ },
96
+ { signal: controller.signal }
97
+ );
98
+ solidJs.onCleanup(() => {
99
+ controller.abort();
100
+ });
101
+ });
102
+ return /* @__PURE__ */ React.createElement(
103
+ primitiveComponent.Primitive.input,
104
+ {
105
+ ...rest,
106
+ id: local.id ?? context.inputId(),
107
+ autoCapitalize: local.autoCapitalize ?? "off",
108
+ autocomplete: local.autocomplete ?? "current-password",
109
+ ref: composeRefs.mergeRefs(local.ref, (el) => context.setInputRef(el)),
110
+ spellcheck: local.spellcheck ?? false,
111
+ type: context.visible() ? "text" : "password",
112
+ "data-state": getVisibilityState(context.visible()),
113
+ onBlur: primitive.composeEventHandlers(
114
+ local.onBlur,
115
+ (event) => {
116
+ const { selectionStart, selectionEnd } = event.currentTarget;
117
+ context.focusState.selectionStart = selectionStart;
118
+ context.focusState.selectionEnd = selectionEnd;
119
+ }
120
+ )
121
+ }
122
+ );
123
+ }
124
+ var PASSWORD_TOGGLE_FIELD_TOGGLE_NAME = PASSWORD_TOGGLE_FIELD_NAME + "Toggle";
125
+ function PasswordToggleFieldToggle(props) {
126
+ const [local, rest] = solidJs.splitProps(props, [
127
+ "__scopePasswordToggleField",
128
+ "onClick",
129
+ "onPointerDown",
130
+ "onPointerCancel",
131
+ "onPointerUp",
132
+ "children",
133
+ "aria-label",
134
+ "aria-controls",
135
+ "aria-hidden",
136
+ "tabIndex",
137
+ "ref"
138
+ ]);
139
+ const context = usePasswordToggleFieldContext(
140
+ PASSWORD_TOGGLE_FIELD_TOGGLE_NAME,
141
+ local.__scopePasswordToggleField
142
+ );
143
+ let elementRef;
144
+ const [internalAriaLabel, setInternalAriaLabel] = solidJs.createSignal(void 0);
145
+ solidJs.createEffect(() => {
146
+ const element = elementRef;
147
+ const ariaLabelProp = local["aria-label"];
148
+ if (!element || ariaLabelProp) {
149
+ setInternalAriaLabel(void 0);
150
+ return;
151
+ }
152
+ const DEFAULT_ARIA_LABEL = context.visible() ? "Hide password" : "Show password";
153
+ function checkForInnerTextLabel(textContent) {
154
+ const text = textContent ? textContent : void 0;
155
+ setInternalAriaLabel(text ? void 0 : DEFAULT_ARIA_LABEL);
156
+ }
157
+ checkForInnerTextLabel(element.textContent);
158
+ const observer = new MutationObserver((entries) => {
159
+ let textContent;
160
+ for (const entry of entries) {
161
+ if (entry.type === "characterData") {
162
+ if (element.textContent) {
163
+ textContent = element.textContent;
164
+ }
165
+ }
166
+ }
167
+ checkForInnerTextLabel(textContent);
168
+ });
169
+ observer.observe(element, { characterData: true, subtree: true });
170
+ solidJs.onCleanup(() => {
171
+ observer.disconnect();
172
+ });
173
+ });
174
+ const ariaLabel = () => local["aria-label"] || internalAriaLabel();
175
+ solidJs.createEffect(() => {
176
+ const ownerWindow = elementRef?.ownerDocument?.defaultView || window;
177
+ let idleCleanup = () => {
178
+ };
179
+ const reset = () => {
180
+ context.focusState.clickTriggered = false;
181
+ };
182
+ const handlePointerUp = () => {
183
+ idleCleanup = requestIdleCallbackCompat(ownerWindow, reset);
184
+ };
185
+ ownerWindow.addEventListener("pointerup", handlePointerUp);
186
+ solidJs.onCleanup(() => {
187
+ idleCleanup();
188
+ ownerWindow.removeEventListener("pointerup", handlePointerUp);
189
+ });
190
+ });
191
+ return /* @__PURE__ */ React.createElement(
192
+ primitiveComponent.Primitive.button,
193
+ {
194
+ "aria-controls": local["aria-controls"] ?? context.inputId(),
195
+ "aria-label": ariaLabel(),
196
+ "data-state": getVisibilityState(context.visible()),
197
+ ...rest,
198
+ ref: composeRefs.mergeRefs(local.ref, (el) => {
199
+ elementRef = el;
200
+ }),
201
+ onPointerDown: primitive.composeEventHandlers(
202
+ local.onPointerDown,
203
+ () => {
204
+ context.focusState.clickTriggered = true;
205
+ }
206
+ ),
207
+ "on:pointercancel": (event) => {
208
+ const handler = local.onPointerCancel;
209
+ if (typeof handler === "function") {
210
+ handler(event);
211
+ }
212
+ Object.assign(context.focusState, INITIAL_FOCUS_STATE);
213
+ },
214
+ "on:click": (event) => {
215
+ const handler = local.onClick;
216
+ if (typeof handler === "function") {
217
+ handler(event);
218
+ }
219
+ if (event.defaultPrevented) {
220
+ Object.assign(context.focusState, INITIAL_FOCUS_STATE);
221
+ return;
222
+ }
223
+ solidJs.batch(() => {
224
+ context.setVisible((prev) => !prev);
225
+ });
226
+ if (context.focusState.clickTriggered) {
227
+ const input = context.inputRef();
228
+ if (input) {
229
+ const { selectionStart, selectionEnd } = context.focusState;
230
+ input.focus();
231
+ if (selectionStart !== null || selectionEnd !== null) {
232
+ requestAnimationFrame(() => {
233
+ if (input.ownerDocument.activeElement === input) {
234
+ input.selectionStart = selectionStart;
235
+ input.selectionEnd = selectionEnd;
236
+ }
237
+ });
238
+ }
239
+ }
240
+ }
241
+ Object.assign(context.focusState, INITIAL_FOCUS_STATE);
242
+ },
243
+ "on:pointerup": (event) => {
244
+ const handler = local.onPointerUp;
245
+ if (typeof handler === "function") {
246
+ handler(event);
247
+ }
248
+ setTimeout(() => {
249
+ Object.assign(context.focusState, INITIAL_FOCUS_STATE);
250
+ }, 50);
251
+ },
252
+ type: "button"
253
+ },
254
+ local.children
255
+ );
256
+ }
257
+ var PASSWORD_TOGGLE_FIELD_SLOT_NAME = PASSWORD_TOGGLE_FIELD_NAME + "Slot";
258
+ function PasswordToggleFieldSlot(props) {
259
+ const [local, rest] = solidJs.splitProps(props, [
260
+ "__scopePasswordToggleField"
261
+ ]);
262
+ const context = usePasswordToggleFieldContext(
263
+ PASSWORD_TOGGLE_FIELD_SLOT_NAME,
264
+ local.__scopePasswordToggleField
265
+ );
266
+ if ("render" in rest) {
267
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, rest.render({ visible: context.visible() }));
268
+ }
269
+ const declarativeProps = rest;
270
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, context.visible() ? declarativeProps.visible : declarativeProps.hidden);
271
+ }
272
+ var PASSWORD_TOGGLE_FIELD_ICON_NAME = PASSWORD_TOGGLE_FIELD_NAME + "Icon";
273
+ function PasswordToggleFieldIcon(props) {
274
+ const [local, rest] = solidJs.splitProps(props, [
275
+ "__scopePasswordToggleField",
276
+ "visible",
277
+ "hidden",
278
+ "ref"
279
+ ]);
280
+ const context = usePasswordToggleFieldContext(
281
+ PASSWORD_TOGGLE_FIELD_ICON_NAME,
282
+ local.__scopePasswordToggleField
283
+ );
284
+ return /* @__PURE__ */ React.createElement(
285
+ primitiveComponent.Primitive.svg,
286
+ {
287
+ ...rest,
288
+ ref: local.ref,
289
+ "aria-hidden": true,
290
+ asChild: true,
291
+ "data-state": getVisibilityState(context.visible())
292
+ },
293
+ context.visible() ? local.visible : local.hidden
294
+ );
295
+ }
296
+ function getVisibilityState(visible) {
297
+ return visible ? "visible" : "hidden";
298
+ }
299
+ function requestIdleCallbackCompat(window2, callback, options) {
300
+ if (window2.requestIdleCallback) {
301
+ const id2 = window2.requestIdleCallback(callback, options);
302
+ return () => {
303
+ window2.cancelIdleCallback(id2);
304
+ };
305
+ }
306
+ const start = Date.now();
307
+ const id = window2.setTimeout(() => {
308
+ const timeRemaining = () => Math.max(0, 50 - (Date.now() - start));
309
+ callback({ didTimeout: false, timeRemaining });
310
+ }, 1);
311
+ return () => {
312
+ window2.clearTimeout(id);
313
+ };
314
+ }
315
+ var Root = PasswordToggleField;
316
+ var Input = PasswordToggleFieldInput;
317
+ var Toggle = PasswordToggleFieldToggle;
318
+ var Slot = PasswordToggleFieldSlot;
319
+ var Icon = PasswordToggleFieldIcon;
320
+
321
+ exports.Icon = Icon;
322
+ exports.Input = Input;
323
+ exports.PasswordToggleField = PasswordToggleField;
324
+ exports.PasswordToggleFieldIcon = PasswordToggleFieldIcon;
325
+ exports.PasswordToggleFieldInput = PasswordToggleFieldInput;
326
+ exports.PasswordToggleFieldSlot = PasswordToggleFieldSlot;
327
+ exports.PasswordToggleFieldToggle = PasswordToggleFieldToggle;
328
+ exports.Root = Root;
329
+ exports.Slot = Slot;
330
+ exports.Toggle = Toggle;
331
+ exports.createPasswordToggleFieldScope = createPasswordToggleFieldScope;
332
+ //# sourceMappingURL=index.cjs.map
333
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/password-toggle-field.tsx"],"names":["createContextScope","splitProps","createId","createSignal","createControllableSignal","createEffect","onCleanup","Primitive","mergeRefs","composeEventHandlers","batch","window","id"],"mappings":"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","file":"index.cjs","sourcesContent":["import {\n type JSX,\n type Accessor,\n createSignal,\n createEffect,\n onCleanup,\n splitProps,\n batch,\n} from 'solid-js';\nimport { composeEventHandlers } from '@radix-solid-js/primitive';\nimport { mergeRefs } from '@radix-solid-js/compose-refs';\nimport { createContextScope } from '@radix-solid-js/context';\nimport { createId } from '@radix-solid-js/id';\nimport { createControllableSignal } from '@radix-solid-js/use-controllable-state';\nimport { Primitive, type PrimitiveProps } from '@radix-solid-js/primitive-component';\n\nimport type { Scope } from '@radix-solid-js/context';\n\n/* -------------------------------------------------------------------------------------------------\n * PasswordToggleField\n * -----------------------------------------------------------------------------------------------*/\n\nconst PASSWORD_TOGGLE_FIELD_NAME = 'PasswordToggleField';\n\ntype ScopedProps<P> = P & { __scopePasswordToggleField?: Scope };\n\ntype InternalFocusState = {\n clickTriggered: boolean;\n selectionStart: number | null;\n selectionEnd: number | null;\n};\n\nconst INITIAL_FOCUS_STATE: InternalFocusState = {\n clickTriggered: false,\n selectionStart: null,\n selectionEnd: null,\n};\n\ninterface PasswordToggleFieldContextValue {\n inputId: Accessor<string>;\n inputRef: Accessor<HTMLInputElement | null>;\n setInputRef: (el: HTMLInputElement | null) => void;\n visible: Accessor<boolean>;\n setVisible: (value: boolean | ((prev: boolean) => boolean)) => void;\n syncInputId: (providedId: string | number | undefined) => void;\n focusState: InternalFocusState;\n}\n\nconst [createPasswordToggleFieldContext, createPasswordToggleFieldScope] =\n createContextScope(PASSWORD_TOGGLE_FIELD_NAME);\n\nconst [PasswordToggleFieldProvider, usePasswordToggleFieldContext] =\n createPasswordToggleFieldContext<PasswordToggleFieldContextValue>(PASSWORD_TOGGLE_FIELD_NAME);\n\n/* -------------------------------------------------------------------------------------------------\n * PasswordToggleField (Root)\n * -----------------------------------------------------------------------------------------------*/\n\ninterface PasswordToggleFieldProps {\n id?: string;\n visible?: boolean;\n defaultVisible?: boolean;\n onVisibilityChange?: (visible: boolean) => void;\n children?: JSX.Element;\n __scopePasswordToggleField?: Scope;\n}\n\nfunction PasswordToggleField(props: PasswordToggleFieldProps) {\n const [local] = splitProps(props, [\n '__scopePasswordToggleField',\n 'id',\n 'visible',\n 'defaultVisible',\n 'onVisibilityChange',\n 'children',\n ]);\n\n const baseId = createId(local.id);\n const defaultInputId = `${baseId}-input`;\n const [inputIdState, setInputIdState] = createSignal<string | null>(defaultInputId);\n const inputId = () => inputIdState() ?? defaultInputId;\n\n const syncInputId = (providedId: string | number | undefined) => {\n setInputIdState(providedId != null ? String(providedId) : null);\n };\n\n const [visible, setVisible] = createControllableSignal<boolean>({\n prop: () => local.visible,\n defaultProp: local.defaultVisible ?? false,\n onChange: local.onVisibilityChange,\n caller: PASSWORD_TOGGLE_FIELD_NAME,\n });\n\n const [inputRef, setInputRef] = createSignal<HTMLInputElement | null>(null);\n const focusState: InternalFocusState = { ...INITIAL_FOCUS_STATE };\n\n return (\n <PasswordToggleFieldProvider\n scope={local.__scopePasswordToggleField}\n inputId={inputId}\n inputRef={inputRef}\n setInputRef={setInputRef}\n visible={visible as Accessor<boolean>}\n setVisible={setVisible}\n syncInputId={syncInputId}\n focusState={focusState}\n >\n {local.children}\n </PasswordToggleFieldProvider>\n );\n}\n\n/* -------------------------------------------------------------------------------------------------\n * PasswordToggleFieldInput\n * -----------------------------------------------------------------------------------------------*/\n\nconst PASSWORD_TOGGLE_FIELD_INPUT_NAME = PASSWORD_TOGGLE_FIELD_NAME + 'Input';\n\ninterface PasswordToggleFieldInputOwnProps {\n autocomplete?: 'current-password' | 'new-password';\n}\n\ninterface PasswordToggleFieldInputProps\n extends PasswordToggleFieldInputOwnProps,\n Omit<PrimitiveProps<'input'>, keyof PasswordToggleFieldInputOwnProps | 'type'> {\n __scopePasswordToggleField?: Scope;\n}\n\nfunction PasswordToggleFieldInput(props: PasswordToggleFieldInputProps) {\n const [local, rest] = splitProps(props, [\n '__scopePasswordToggleField',\n 'autocomplete',\n 'autoCapitalize',\n 'spellcheck',\n 'id',\n 'ref',\n 'onBlur',\n ]);\n\n const context = usePasswordToggleFieldContext(\n PASSWORD_TOGGLE_FIELD_INPUT_NAME,\n local.__scopePasswordToggleField,\n );\n\n // Sync provided id to context\n createEffect(() => {\n context.syncInputId(local.id);\n });\n\n // Reset visibility on form reset/submit\n createEffect(() => {\n const inputElement = context.inputRef();\n const form = inputElement?.form;\n if (!form) return;\n\n const controller = new AbortController();\n\n form.addEventListener(\n 'reset',\n (event) => {\n if (!event.defaultPrevented) {\n context.setVisible(false);\n }\n },\n { signal: controller.signal },\n );\n\n form.addEventListener(\n 'submit',\n () => {\n // Always reset the visibility on submit regardless of whether the\n // default action is prevented\n context.setVisible(false);\n },\n { signal: controller.signal },\n );\n\n onCleanup(() => {\n controller.abort();\n });\n });\n\n return (\n <Primitive.input\n {...rest}\n id={local.id ?? context.inputId()}\n autoCapitalize={local.autoCapitalize ?? 'off'}\n autocomplete={local.autocomplete ?? 'current-password'}\n ref={mergeRefs(local.ref, (el: any) => context.setInputRef(el as HTMLInputElement))}\n spellcheck={local.spellcheck ?? false}\n type={context.visible() ? 'text' : 'password'}\n data-state={getVisibilityState(context.visible())}\n onBlur={composeEventHandlers(\n local.onBlur as JSX.EventHandler<HTMLInputElement, FocusEvent>,\n (event) => {\n const { selectionStart, selectionEnd } = event.currentTarget;\n context.focusState.selectionStart = selectionStart;\n context.focusState.selectionEnd = selectionEnd;\n },\n )}\n />\n );\n}\n\n/* -------------------------------------------------------------------------------------------------\n * PasswordToggleFieldToggle\n * -----------------------------------------------------------------------------------------------*/\n\nconst PASSWORD_TOGGLE_FIELD_TOGGLE_NAME = PASSWORD_TOGGLE_FIELD_NAME + 'Toggle';\n\ninterface PasswordToggleFieldToggleProps extends Omit<PrimitiveProps<'button'>, 'type'> {\n __scopePasswordToggleField?: Scope;\n}\n\nfunction PasswordToggleFieldToggle(props: PasswordToggleFieldToggleProps) {\n const [local, rest] = splitProps(props, [\n '__scopePasswordToggleField',\n 'onClick',\n 'onPointerDown',\n 'onPointerCancel',\n 'onPointerUp',\n 'children',\n 'aria-label',\n 'aria-controls',\n 'aria-hidden',\n 'tabIndex',\n 'ref',\n ]);\n\n const context = usePasswordToggleFieldContext(\n PASSWORD_TOGGLE_FIELD_TOGGLE_NAME,\n local.__scopePasswordToggleField,\n );\n\n let elementRef: HTMLButtonElement | undefined;\n\n // Auto-generate aria-label if no text content and no explicit aria-label\n const [internalAriaLabel, setInternalAriaLabel] = createSignal<string | undefined>(undefined);\n\n createEffect(() => {\n const element = elementRef;\n const ariaLabelProp = local['aria-label'];\n if (!element || ariaLabelProp) {\n setInternalAriaLabel(undefined);\n return;\n }\n\n const DEFAULT_ARIA_LABEL = context.visible() ? 'Hide password' : 'Show password';\n\n function checkForInnerTextLabel(textContent: string | undefined | null) {\n const text = textContent ? textContent : undefined;\n setInternalAriaLabel(text ? undefined : DEFAULT_ARIA_LABEL);\n }\n\n checkForInnerTextLabel(element.textContent);\n\n const observer = new MutationObserver((entries) => {\n let textContent: string | undefined;\n for (const entry of entries) {\n if (entry.type === 'characterData') {\n if (element.textContent) {\n textContent = element.textContent;\n }\n }\n }\n checkForInnerTextLabel(textContent);\n });\n observer.observe(element, { characterData: true, subtree: true });\n\n onCleanup(() => {\n observer.disconnect();\n });\n });\n\n const ariaLabel = () => local['aria-label'] || internalAriaLabel();\n\n // Reset clickTriggered on global pointerup\n createEffect(() => {\n const ownerWindow = elementRef?.ownerDocument?.defaultView || window;\n\n let idleCleanup = () => {};\n const reset = () => {\n context.focusState.clickTriggered = false;\n };\n const handlePointerUp = () => {\n idleCleanup = requestIdleCallbackCompat(ownerWindow, reset);\n };\n\n ownerWindow.addEventListener('pointerup', handlePointerUp);\n\n onCleanup(() => {\n idleCleanup();\n ownerWindow.removeEventListener('pointerup', handlePointerUp);\n });\n });\n\n return (\n <Primitive.button\n aria-controls={local['aria-controls'] ?? context.inputId()}\n aria-label={ariaLabel()}\n data-state={getVisibilityState(context.visible())}\n {...rest}\n ref={mergeRefs(local.ref, (el: any) => {\n elementRef = el as HTMLButtonElement;\n })}\n onPointerDown={composeEventHandlers(\n local.onPointerDown as JSX.EventHandler<HTMLButtonElement, PointerEvent>,\n () => {\n context.focusState.clickTriggered = true;\n },\n )}\n on:pointercancel={(event: PointerEvent) => {\n const handler = local.onPointerCancel;\n if (typeof handler === 'function') {\n (handler as any)(event);\n }\n // Always reset focus state on cancellation\n Object.assign(context.focusState, INITIAL_FOCUS_STATE);\n }}\n on:click={(event: MouseEvent) => {\n const handler = local.onClick;\n if (typeof handler === 'function') {\n (handler as any)(event);\n }\n if (event.defaultPrevented) {\n Object.assign(context.focusState, INITIAL_FOCUS_STATE);\n return;\n }\n\n // Toggle visibility synchronously\n batch(() => {\n context.setVisible((prev) => !prev);\n });\n\n if (context.focusState.clickTriggered) {\n const input = context.inputRef();\n if (input) {\n const { selectionStart, selectionEnd } = context.focusState;\n input.focus();\n if (selectionStart !== null || selectionEnd !== null) {\n // Wait a tick so that focus has settled, then restore selection position\n requestAnimationFrame(() => {\n if (input.ownerDocument.activeElement === input) {\n input.selectionStart = selectionStart;\n input.selectionEnd = selectionEnd;\n }\n });\n }\n }\n }\n Object.assign(context.focusState, INITIAL_FOCUS_STATE);\n }}\n on:pointerup={(event: PointerEvent) => {\n const handler = local.onPointerUp;\n if (typeof handler === 'function') {\n (handler as any)(event);\n }\n // If click handler hasn't been called at this point, it may have been\n // intercepted, in which case we still want to reset our internal state\n setTimeout(() => {\n Object.assign(context.focusState, INITIAL_FOCUS_STATE);\n }, 50);\n }}\n type=\"button\"\n >\n {local.children}\n </Primitive.button>\n );\n}\n\n/* -------------------------------------------------------------------------------------------------\n * PasswordToggleFieldSlot\n * -----------------------------------------------------------------------------------------------*/\n\nconst PASSWORD_TOGGLE_FIELD_SLOT_NAME = PASSWORD_TOGGLE_FIELD_NAME + 'Slot';\n\ninterface PasswordToggleFieldSlotDeclarativeProps {\n visible: JSX.Element;\n hidden: JSX.Element;\n __scopePasswordToggleField?: Scope;\n}\n\ninterface PasswordToggleFieldSlotRenderProps {\n render: (args: { visible: boolean }) => JSX.Element;\n __scopePasswordToggleField?: Scope;\n}\n\ntype PasswordToggleFieldSlotProps =\n | PasswordToggleFieldSlotDeclarativeProps\n | PasswordToggleFieldSlotRenderProps;\n\nfunction PasswordToggleFieldSlot(props: PasswordToggleFieldSlotProps) {\n const [local, rest] = splitProps(props as ScopedProps<PasswordToggleFieldSlotProps>, [\n '__scopePasswordToggleField',\n ]);\n\n const context = usePasswordToggleFieldContext(\n PASSWORD_TOGGLE_FIELD_SLOT_NAME,\n local.__scopePasswordToggleField,\n );\n\n if ('render' in rest) {\n return <>{(rest as PasswordToggleFieldSlotRenderProps).render({ visible: context.visible() })}</>;\n }\n\n const declarativeProps = rest as PasswordToggleFieldSlotDeclarativeProps;\n return <>{context.visible() ? declarativeProps.visible : declarativeProps.hidden}</>;\n}\n\n/* -------------------------------------------------------------------------------------------------\n * PasswordToggleFieldIcon\n * -----------------------------------------------------------------------------------------------*/\n\nconst PASSWORD_TOGGLE_FIELD_ICON_NAME = PASSWORD_TOGGLE_FIELD_NAME + 'Icon';\n\ninterface PasswordToggleFieldIconProps extends Omit<PrimitiveProps<'svg'>, 'children'> {\n visible: JSX.Element;\n hidden: JSX.Element;\n __scopePasswordToggleField?: Scope;\n}\n\nfunction PasswordToggleFieldIcon(props: PasswordToggleFieldIconProps) {\n const [local, rest] = splitProps(props, [\n '__scopePasswordToggleField',\n 'visible',\n 'hidden',\n 'ref',\n ]);\n\n const context = usePasswordToggleFieldContext(\n PASSWORD_TOGGLE_FIELD_ICON_NAME,\n local.__scopePasswordToggleField,\n );\n\n return (\n <Primitive.svg\n {...rest}\n ref={local.ref}\n aria-hidden\n asChild\n data-state={getVisibilityState(context.visible())}\n >\n {context.visible() ? local.visible : local.hidden}\n </Primitive.svg>\n );\n}\n\n/* -------------------------------------------------------------------------------------------------\n * Utils\n * -----------------------------------------------------------------------------------------------*/\n\nfunction getVisibilityState(visible: boolean): 'visible' | 'hidden' {\n return visible ? 'visible' : 'hidden';\n}\n\nfunction requestIdleCallbackCompat(\n window: Window,\n callback: IdleRequestCallback,\n options?: IdleRequestOptions,\n): () => void {\n if ((window as any).requestIdleCallback) {\n const id = window.requestIdleCallback(callback, options);\n return () => {\n window.cancelIdleCallback(id);\n };\n }\n const start = Date.now();\n const id = window.setTimeout(() => {\n const timeRemaining = () => Math.max(0, 50 - (Date.now() - start));\n callback({ didTimeout: false, timeRemaining });\n }, 1);\n return () => {\n window.clearTimeout(id);\n };\n}\n\n/* ---------------------------------------------------------------------------------------------- */\n\nconst Root = PasswordToggleField;\nconst Input = PasswordToggleFieldInput;\nconst Toggle = PasswordToggleFieldToggle;\nconst Slot = PasswordToggleFieldSlot;\nconst Icon = PasswordToggleFieldIcon;\n\nexport {\n createPasswordToggleFieldScope,\n //\n PasswordToggleField,\n PasswordToggleFieldInput,\n PasswordToggleFieldToggle,\n PasswordToggleFieldSlot,\n PasswordToggleFieldIcon,\n //\n Root,\n Input,\n Toggle,\n Slot,\n Icon,\n};\nexport type {\n PasswordToggleFieldProps,\n PasswordToggleFieldInputProps,\n PasswordToggleFieldToggleProps,\n PasswordToggleFieldSlotProps,\n PasswordToggleFieldIconProps,\n};\n"]}
@@ -0,0 +1,52 @@
1
+ import * as _radix_solid_js_context from '@radix-solid-js/context';
2
+ import { Scope } from '@radix-solid-js/context';
3
+ import { JSX } from 'solid-js';
4
+ import { PrimitiveProps } from '@radix-solid-js/primitive-component';
5
+
6
+ declare const createPasswordToggleFieldScope: _radix_solid_js_context.CreateScope;
7
+ interface PasswordToggleFieldProps {
8
+ id?: string;
9
+ visible?: boolean;
10
+ defaultVisible?: boolean;
11
+ onVisibilityChange?: (visible: boolean) => void;
12
+ children?: JSX.Element;
13
+ __scopePasswordToggleField?: Scope;
14
+ }
15
+ declare function PasswordToggleField(props: PasswordToggleFieldProps): JSX.Element;
16
+ interface PasswordToggleFieldInputOwnProps {
17
+ autocomplete?: 'current-password' | 'new-password';
18
+ }
19
+ interface PasswordToggleFieldInputProps extends PasswordToggleFieldInputOwnProps, Omit<PrimitiveProps<'input'>, keyof PasswordToggleFieldInputOwnProps | 'type'> {
20
+ __scopePasswordToggleField?: Scope;
21
+ }
22
+ declare function PasswordToggleFieldInput(props: PasswordToggleFieldInputProps): JSX.Element;
23
+ interface PasswordToggleFieldToggleProps extends Omit<PrimitiveProps<'button'>, 'type'> {
24
+ __scopePasswordToggleField?: Scope;
25
+ }
26
+ declare function PasswordToggleFieldToggle(props: PasswordToggleFieldToggleProps): JSX.Element;
27
+ interface PasswordToggleFieldSlotDeclarativeProps {
28
+ visible: JSX.Element;
29
+ hidden: JSX.Element;
30
+ __scopePasswordToggleField?: Scope;
31
+ }
32
+ interface PasswordToggleFieldSlotRenderProps {
33
+ render: (args: {
34
+ visible: boolean;
35
+ }) => JSX.Element;
36
+ __scopePasswordToggleField?: Scope;
37
+ }
38
+ type PasswordToggleFieldSlotProps = PasswordToggleFieldSlotDeclarativeProps | PasswordToggleFieldSlotRenderProps;
39
+ declare function PasswordToggleFieldSlot(props: PasswordToggleFieldSlotProps): JSX.Element;
40
+ interface PasswordToggleFieldIconProps extends Omit<PrimitiveProps<'svg'>, 'children'> {
41
+ visible: JSX.Element;
42
+ hidden: JSX.Element;
43
+ __scopePasswordToggleField?: Scope;
44
+ }
45
+ declare function PasswordToggleFieldIcon(props: PasswordToggleFieldIconProps): JSX.Element;
46
+ declare const Root: typeof PasswordToggleField;
47
+ declare const Input: typeof PasswordToggleFieldInput;
48
+ declare const Toggle: typeof PasswordToggleFieldToggle;
49
+ declare const Slot: typeof PasswordToggleFieldSlot;
50
+ declare const Icon: typeof PasswordToggleFieldIcon;
51
+
52
+ export { Icon, Input, PasswordToggleField, PasswordToggleFieldIcon, type PasswordToggleFieldIconProps, PasswordToggleFieldInput, type PasswordToggleFieldInputProps, type PasswordToggleFieldProps, PasswordToggleFieldSlot, type PasswordToggleFieldSlotProps, PasswordToggleFieldToggle, type PasswordToggleFieldToggleProps, Root, Slot, Toggle, createPasswordToggleFieldScope };
@@ -0,0 +1,52 @@
1
+ import * as _radix_solid_js_context from '@radix-solid-js/context';
2
+ import { Scope } from '@radix-solid-js/context';
3
+ import { JSX } from 'solid-js';
4
+ import { PrimitiveProps } from '@radix-solid-js/primitive-component';
5
+
6
+ declare const createPasswordToggleFieldScope: _radix_solid_js_context.CreateScope;
7
+ interface PasswordToggleFieldProps {
8
+ id?: string;
9
+ visible?: boolean;
10
+ defaultVisible?: boolean;
11
+ onVisibilityChange?: (visible: boolean) => void;
12
+ children?: JSX.Element;
13
+ __scopePasswordToggleField?: Scope;
14
+ }
15
+ declare function PasswordToggleField(props: PasswordToggleFieldProps): JSX.Element;
16
+ interface PasswordToggleFieldInputOwnProps {
17
+ autocomplete?: 'current-password' | 'new-password';
18
+ }
19
+ interface PasswordToggleFieldInputProps extends PasswordToggleFieldInputOwnProps, Omit<PrimitiveProps<'input'>, keyof PasswordToggleFieldInputOwnProps | 'type'> {
20
+ __scopePasswordToggleField?: Scope;
21
+ }
22
+ declare function PasswordToggleFieldInput(props: PasswordToggleFieldInputProps): JSX.Element;
23
+ interface PasswordToggleFieldToggleProps extends Omit<PrimitiveProps<'button'>, 'type'> {
24
+ __scopePasswordToggleField?: Scope;
25
+ }
26
+ declare function PasswordToggleFieldToggle(props: PasswordToggleFieldToggleProps): JSX.Element;
27
+ interface PasswordToggleFieldSlotDeclarativeProps {
28
+ visible: JSX.Element;
29
+ hidden: JSX.Element;
30
+ __scopePasswordToggleField?: Scope;
31
+ }
32
+ interface PasswordToggleFieldSlotRenderProps {
33
+ render: (args: {
34
+ visible: boolean;
35
+ }) => JSX.Element;
36
+ __scopePasswordToggleField?: Scope;
37
+ }
38
+ type PasswordToggleFieldSlotProps = PasswordToggleFieldSlotDeclarativeProps | PasswordToggleFieldSlotRenderProps;
39
+ declare function PasswordToggleFieldSlot(props: PasswordToggleFieldSlotProps): JSX.Element;
40
+ interface PasswordToggleFieldIconProps extends Omit<PrimitiveProps<'svg'>, 'children'> {
41
+ visible: JSX.Element;
42
+ hidden: JSX.Element;
43
+ __scopePasswordToggleField?: Scope;
44
+ }
45
+ declare function PasswordToggleFieldIcon(props: PasswordToggleFieldIconProps): JSX.Element;
46
+ declare const Root: typeof PasswordToggleField;
47
+ declare const Input: typeof PasswordToggleFieldInput;
48
+ declare const Toggle: typeof PasswordToggleFieldToggle;
49
+ declare const Slot: typeof PasswordToggleFieldSlot;
50
+ declare const Icon: typeof PasswordToggleFieldIcon;
51
+
52
+ export { Icon, Input, PasswordToggleField, PasswordToggleFieldIcon, type PasswordToggleFieldIconProps, PasswordToggleFieldInput, type PasswordToggleFieldInputProps, type PasswordToggleFieldProps, PasswordToggleFieldSlot, type PasswordToggleFieldSlotProps, PasswordToggleFieldToggle, type PasswordToggleFieldToggleProps, Root, Slot, Toggle, createPasswordToggleFieldScope };
package/dist/index.js ADDED
@@ -0,0 +1,321 @@
1
+ import { splitProps, createSignal, createEffect, onCleanup, batch } from 'solid-js';
2
+ import { composeEventHandlers } from '@radix-solid-js/primitive';
3
+ import { mergeRefs } from '@radix-solid-js/compose-refs';
4
+ import { createContextScope } from '@radix-solid-js/context';
5
+ import { createId } from '@radix-solid-js/id';
6
+ import { createControllableSignal } from '@radix-solid-js/use-controllable-state';
7
+ import { Primitive } from '@radix-solid-js/primitive-component';
8
+
9
+ // src/password-toggle-field.tsx
10
+ var PASSWORD_TOGGLE_FIELD_NAME = "PasswordToggleField";
11
+ var INITIAL_FOCUS_STATE = {
12
+ clickTriggered: false,
13
+ selectionStart: null,
14
+ selectionEnd: null
15
+ };
16
+ var [createPasswordToggleFieldContext, createPasswordToggleFieldScope] = createContextScope(PASSWORD_TOGGLE_FIELD_NAME);
17
+ var [PasswordToggleFieldProvider, usePasswordToggleFieldContext] = createPasswordToggleFieldContext(PASSWORD_TOGGLE_FIELD_NAME);
18
+ function PasswordToggleField(props) {
19
+ const [local] = splitProps(props, [
20
+ "__scopePasswordToggleField",
21
+ "id",
22
+ "visible",
23
+ "defaultVisible",
24
+ "onVisibilityChange",
25
+ "children"
26
+ ]);
27
+ const baseId = createId(local.id);
28
+ const defaultInputId = `${baseId}-input`;
29
+ const [inputIdState, setInputIdState] = createSignal(defaultInputId);
30
+ const inputId = () => inputIdState() ?? defaultInputId;
31
+ const syncInputId = (providedId) => {
32
+ setInputIdState(providedId != null ? String(providedId) : null);
33
+ };
34
+ const [visible, setVisible] = createControllableSignal({
35
+ prop: () => local.visible,
36
+ defaultProp: local.defaultVisible ?? false,
37
+ onChange: local.onVisibilityChange,
38
+ caller: PASSWORD_TOGGLE_FIELD_NAME
39
+ });
40
+ const [inputRef, setInputRef] = createSignal(null);
41
+ const focusState = { ...INITIAL_FOCUS_STATE };
42
+ return /* @__PURE__ */ React.createElement(
43
+ PasswordToggleFieldProvider,
44
+ {
45
+ scope: local.__scopePasswordToggleField,
46
+ inputId,
47
+ inputRef,
48
+ setInputRef,
49
+ visible,
50
+ setVisible,
51
+ syncInputId,
52
+ focusState
53
+ },
54
+ local.children
55
+ );
56
+ }
57
+ var PASSWORD_TOGGLE_FIELD_INPUT_NAME = PASSWORD_TOGGLE_FIELD_NAME + "Input";
58
+ function PasswordToggleFieldInput(props) {
59
+ const [local, rest] = splitProps(props, [
60
+ "__scopePasswordToggleField",
61
+ "autocomplete",
62
+ "autoCapitalize",
63
+ "spellcheck",
64
+ "id",
65
+ "ref",
66
+ "onBlur"
67
+ ]);
68
+ const context = usePasswordToggleFieldContext(
69
+ PASSWORD_TOGGLE_FIELD_INPUT_NAME,
70
+ local.__scopePasswordToggleField
71
+ );
72
+ createEffect(() => {
73
+ context.syncInputId(local.id);
74
+ });
75
+ createEffect(() => {
76
+ const inputElement = context.inputRef();
77
+ const form = inputElement?.form;
78
+ if (!form) return;
79
+ const controller = new AbortController();
80
+ form.addEventListener(
81
+ "reset",
82
+ (event) => {
83
+ if (!event.defaultPrevented) {
84
+ context.setVisible(false);
85
+ }
86
+ },
87
+ { signal: controller.signal }
88
+ );
89
+ form.addEventListener(
90
+ "submit",
91
+ () => {
92
+ context.setVisible(false);
93
+ },
94
+ { signal: controller.signal }
95
+ );
96
+ onCleanup(() => {
97
+ controller.abort();
98
+ });
99
+ });
100
+ return /* @__PURE__ */ React.createElement(
101
+ Primitive.input,
102
+ {
103
+ ...rest,
104
+ id: local.id ?? context.inputId(),
105
+ autoCapitalize: local.autoCapitalize ?? "off",
106
+ autocomplete: local.autocomplete ?? "current-password",
107
+ ref: mergeRefs(local.ref, (el) => context.setInputRef(el)),
108
+ spellcheck: local.spellcheck ?? false,
109
+ type: context.visible() ? "text" : "password",
110
+ "data-state": getVisibilityState(context.visible()),
111
+ onBlur: composeEventHandlers(
112
+ local.onBlur,
113
+ (event) => {
114
+ const { selectionStart, selectionEnd } = event.currentTarget;
115
+ context.focusState.selectionStart = selectionStart;
116
+ context.focusState.selectionEnd = selectionEnd;
117
+ }
118
+ )
119
+ }
120
+ );
121
+ }
122
+ var PASSWORD_TOGGLE_FIELD_TOGGLE_NAME = PASSWORD_TOGGLE_FIELD_NAME + "Toggle";
123
+ function PasswordToggleFieldToggle(props) {
124
+ const [local, rest] = splitProps(props, [
125
+ "__scopePasswordToggleField",
126
+ "onClick",
127
+ "onPointerDown",
128
+ "onPointerCancel",
129
+ "onPointerUp",
130
+ "children",
131
+ "aria-label",
132
+ "aria-controls",
133
+ "aria-hidden",
134
+ "tabIndex",
135
+ "ref"
136
+ ]);
137
+ const context = usePasswordToggleFieldContext(
138
+ PASSWORD_TOGGLE_FIELD_TOGGLE_NAME,
139
+ local.__scopePasswordToggleField
140
+ );
141
+ let elementRef;
142
+ const [internalAriaLabel, setInternalAriaLabel] = createSignal(void 0);
143
+ createEffect(() => {
144
+ const element = elementRef;
145
+ const ariaLabelProp = local["aria-label"];
146
+ if (!element || ariaLabelProp) {
147
+ setInternalAriaLabel(void 0);
148
+ return;
149
+ }
150
+ const DEFAULT_ARIA_LABEL = context.visible() ? "Hide password" : "Show password";
151
+ function checkForInnerTextLabel(textContent) {
152
+ const text = textContent ? textContent : void 0;
153
+ setInternalAriaLabel(text ? void 0 : DEFAULT_ARIA_LABEL);
154
+ }
155
+ checkForInnerTextLabel(element.textContent);
156
+ const observer = new MutationObserver((entries) => {
157
+ let textContent;
158
+ for (const entry of entries) {
159
+ if (entry.type === "characterData") {
160
+ if (element.textContent) {
161
+ textContent = element.textContent;
162
+ }
163
+ }
164
+ }
165
+ checkForInnerTextLabel(textContent);
166
+ });
167
+ observer.observe(element, { characterData: true, subtree: true });
168
+ onCleanup(() => {
169
+ observer.disconnect();
170
+ });
171
+ });
172
+ const ariaLabel = () => local["aria-label"] || internalAriaLabel();
173
+ createEffect(() => {
174
+ const ownerWindow = elementRef?.ownerDocument?.defaultView || window;
175
+ let idleCleanup = () => {
176
+ };
177
+ const reset = () => {
178
+ context.focusState.clickTriggered = false;
179
+ };
180
+ const handlePointerUp = () => {
181
+ idleCleanup = requestIdleCallbackCompat(ownerWindow, reset);
182
+ };
183
+ ownerWindow.addEventListener("pointerup", handlePointerUp);
184
+ onCleanup(() => {
185
+ idleCleanup();
186
+ ownerWindow.removeEventListener("pointerup", handlePointerUp);
187
+ });
188
+ });
189
+ return /* @__PURE__ */ React.createElement(
190
+ Primitive.button,
191
+ {
192
+ "aria-controls": local["aria-controls"] ?? context.inputId(),
193
+ "aria-label": ariaLabel(),
194
+ "data-state": getVisibilityState(context.visible()),
195
+ ...rest,
196
+ ref: mergeRefs(local.ref, (el) => {
197
+ elementRef = el;
198
+ }),
199
+ onPointerDown: composeEventHandlers(
200
+ local.onPointerDown,
201
+ () => {
202
+ context.focusState.clickTriggered = true;
203
+ }
204
+ ),
205
+ "on:pointercancel": (event) => {
206
+ const handler = local.onPointerCancel;
207
+ if (typeof handler === "function") {
208
+ handler(event);
209
+ }
210
+ Object.assign(context.focusState, INITIAL_FOCUS_STATE);
211
+ },
212
+ "on:click": (event) => {
213
+ const handler = local.onClick;
214
+ if (typeof handler === "function") {
215
+ handler(event);
216
+ }
217
+ if (event.defaultPrevented) {
218
+ Object.assign(context.focusState, INITIAL_FOCUS_STATE);
219
+ return;
220
+ }
221
+ batch(() => {
222
+ context.setVisible((prev) => !prev);
223
+ });
224
+ if (context.focusState.clickTriggered) {
225
+ const input = context.inputRef();
226
+ if (input) {
227
+ const { selectionStart, selectionEnd } = context.focusState;
228
+ input.focus();
229
+ if (selectionStart !== null || selectionEnd !== null) {
230
+ requestAnimationFrame(() => {
231
+ if (input.ownerDocument.activeElement === input) {
232
+ input.selectionStart = selectionStart;
233
+ input.selectionEnd = selectionEnd;
234
+ }
235
+ });
236
+ }
237
+ }
238
+ }
239
+ Object.assign(context.focusState, INITIAL_FOCUS_STATE);
240
+ },
241
+ "on:pointerup": (event) => {
242
+ const handler = local.onPointerUp;
243
+ if (typeof handler === "function") {
244
+ handler(event);
245
+ }
246
+ setTimeout(() => {
247
+ Object.assign(context.focusState, INITIAL_FOCUS_STATE);
248
+ }, 50);
249
+ },
250
+ type: "button"
251
+ },
252
+ local.children
253
+ );
254
+ }
255
+ var PASSWORD_TOGGLE_FIELD_SLOT_NAME = PASSWORD_TOGGLE_FIELD_NAME + "Slot";
256
+ function PasswordToggleFieldSlot(props) {
257
+ const [local, rest] = splitProps(props, [
258
+ "__scopePasswordToggleField"
259
+ ]);
260
+ const context = usePasswordToggleFieldContext(
261
+ PASSWORD_TOGGLE_FIELD_SLOT_NAME,
262
+ local.__scopePasswordToggleField
263
+ );
264
+ if ("render" in rest) {
265
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, rest.render({ visible: context.visible() }));
266
+ }
267
+ const declarativeProps = rest;
268
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, context.visible() ? declarativeProps.visible : declarativeProps.hidden);
269
+ }
270
+ var PASSWORD_TOGGLE_FIELD_ICON_NAME = PASSWORD_TOGGLE_FIELD_NAME + "Icon";
271
+ function PasswordToggleFieldIcon(props) {
272
+ const [local, rest] = splitProps(props, [
273
+ "__scopePasswordToggleField",
274
+ "visible",
275
+ "hidden",
276
+ "ref"
277
+ ]);
278
+ const context = usePasswordToggleFieldContext(
279
+ PASSWORD_TOGGLE_FIELD_ICON_NAME,
280
+ local.__scopePasswordToggleField
281
+ );
282
+ return /* @__PURE__ */ React.createElement(
283
+ Primitive.svg,
284
+ {
285
+ ...rest,
286
+ ref: local.ref,
287
+ "aria-hidden": true,
288
+ asChild: true,
289
+ "data-state": getVisibilityState(context.visible())
290
+ },
291
+ context.visible() ? local.visible : local.hidden
292
+ );
293
+ }
294
+ function getVisibilityState(visible) {
295
+ return visible ? "visible" : "hidden";
296
+ }
297
+ function requestIdleCallbackCompat(window2, callback, options) {
298
+ if (window2.requestIdleCallback) {
299
+ const id2 = window2.requestIdleCallback(callback, options);
300
+ return () => {
301
+ window2.cancelIdleCallback(id2);
302
+ };
303
+ }
304
+ const start = Date.now();
305
+ const id = window2.setTimeout(() => {
306
+ const timeRemaining = () => Math.max(0, 50 - (Date.now() - start));
307
+ callback({ didTimeout: false, timeRemaining });
308
+ }, 1);
309
+ return () => {
310
+ window2.clearTimeout(id);
311
+ };
312
+ }
313
+ var Root = PasswordToggleField;
314
+ var Input = PasswordToggleFieldInput;
315
+ var Toggle = PasswordToggleFieldToggle;
316
+ var Slot = PasswordToggleFieldSlot;
317
+ var Icon = PasswordToggleFieldIcon;
318
+
319
+ export { Icon, Input, PasswordToggleField, PasswordToggleFieldIcon, PasswordToggleFieldInput, PasswordToggleFieldSlot, PasswordToggleFieldToggle, Root, Slot, Toggle, createPasswordToggleFieldScope };
320
+ //# sourceMappingURL=index.js.map
321
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/password-toggle-field.tsx"],"names":["window","id"],"mappings":"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","file":"index.js","sourcesContent":["import {\n type JSX,\n type Accessor,\n createSignal,\n createEffect,\n onCleanup,\n splitProps,\n batch,\n} from 'solid-js';\nimport { composeEventHandlers } from '@radix-solid-js/primitive';\nimport { mergeRefs } from '@radix-solid-js/compose-refs';\nimport { createContextScope } from '@radix-solid-js/context';\nimport { createId } from '@radix-solid-js/id';\nimport { createControllableSignal } from '@radix-solid-js/use-controllable-state';\nimport { Primitive, type PrimitiveProps } from '@radix-solid-js/primitive-component';\n\nimport type { Scope } from '@radix-solid-js/context';\n\n/* -------------------------------------------------------------------------------------------------\n * PasswordToggleField\n * -----------------------------------------------------------------------------------------------*/\n\nconst PASSWORD_TOGGLE_FIELD_NAME = 'PasswordToggleField';\n\ntype ScopedProps<P> = P & { __scopePasswordToggleField?: Scope };\n\ntype InternalFocusState = {\n clickTriggered: boolean;\n selectionStart: number | null;\n selectionEnd: number | null;\n};\n\nconst INITIAL_FOCUS_STATE: InternalFocusState = {\n clickTriggered: false,\n selectionStart: null,\n selectionEnd: null,\n};\n\ninterface PasswordToggleFieldContextValue {\n inputId: Accessor<string>;\n inputRef: Accessor<HTMLInputElement | null>;\n setInputRef: (el: HTMLInputElement | null) => void;\n visible: Accessor<boolean>;\n setVisible: (value: boolean | ((prev: boolean) => boolean)) => void;\n syncInputId: (providedId: string | number | undefined) => void;\n focusState: InternalFocusState;\n}\n\nconst [createPasswordToggleFieldContext, createPasswordToggleFieldScope] =\n createContextScope(PASSWORD_TOGGLE_FIELD_NAME);\n\nconst [PasswordToggleFieldProvider, usePasswordToggleFieldContext] =\n createPasswordToggleFieldContext<PasswordToggleFieldContextValue>(PASSWORD_TOGGLE_FIELD_NAME);\n\n/* -------------------------------------------------------------------------------------------------\n * PasswordToggleField (Root)\n * -----------------------------------------------------------------------------------------------*/\n\ninterface PasswordToggleFieldProps {\n id?: string;\n visible?: boolean;\n defaultVisible?: boolean;\n onVisibilityChange?: (visible: boolean) => void;\n children?: JSX.Element;\n __scopePasswordToggleField?: Scope;\n}\n\nfunction PasswordToggleField(props: PasswordToggleFieldProps) {\n const [local] = splitProps(props, [\n '__scopePasswordToggleField',\n 'id',\n 'visible',\n 'defaultVisible',\n 'onVisibilityChange',\n 'children',\n ]);\n\n const baseId = createId(local.id);\n const defaultInputId = `${baseId}-input`;\n const [inputIdState, setInputIdState] = createSignal<string | null>(defaultInputId);\n const inputId = () => inputIdState() ?? defaultInputId;\n\n const syncInputId = (providedId: string | number | undefined) => {\n setInputIdState(providedId != null ? String(providedId) : null);\n };\n\n const [visible, setVisible] = createControllableSignal<boolean>({\n prop: () => local.visible,\n defaultProp: local.defaultVisible ?? false,\n onChange: local.onVisibilityChange,\n caller: PASSWORD_TOGGLE_FIELD_NAME,\n });\n\n const [inputRef, setInputRef] = createSignal<HTMLInputElement | null>(null);\n const focusState: InternalFocusState = { ...INITIAL_FOCUS_STATE };\n\n return (\n <PasswordToggleFieldProvider\n scope={local.__scopePasswordToggleField}\n inputId={inputId}\n inputRef={inputRef}\n setInputRef={setInputRef}\n visible={visible as Accessor<boolean>}\n setVisible={setVisible}\n syncInputId={syncInputId}\n focusState={focusState}\n >\n {local.children}\n </PasswordToggleFieldProvider>\n );\n}\n\n/* -------------------------------------------------------------------------------------------------\n * PasswordToggleFieldInput\n * -----------------------------------------------------------------------------------------------*/\n\nconst PASSWORD_TOGGLE_FIELD_INPUT_NAME = PASSWORD_TOGGLE_FIELD_NAME + 'Input';\n\ninterface PasswordToggleFieldInputOwnProps {\n autocomplete?: 'current-password' | 'new-password';\n}\n\ninterface PasswordToggleFieldInputProps\n extends PasswordToggleFieldInputOwnProps,\n Omit<PrimitiveProps<'input'>, keyof PasswordToggleFieldInputOwnProps | 'type'> {\n __scopePasswordToggleField?: Scope;\n}\n\nfunction PasswordToggleFieldInput(props: PasswordToggleFieldInputProps) {\n const [local, rest] = splitProps(props, [\n '__scopePasswordToggleField',\n 'autocomplete',\n 'autoCapitalize',\n 'spellcheck',\n 'id',\n 'ref',\n 'onBlur',\n ]);\n\n const context = usePasswordToggleFieldContext(\n PASSWORD_TOGGLE_FIELD_INPUT_NAME,\n local.__scopePasswordToggleField,\n );\n\n // Sync provided id to context\n createEffect(() => {\n context.syncInputId(local.id);\n });\n\n // Reset visibility on form reset/submit\n createEffect(() => {\n const inputElement = context.inputRef();\n const form = inputElement?.form;\n if (!form) return;\n\n const controller = new AbortController();\n\n form.addEventListener(\n 'reset',\n (event) => {\n if (!event.defaultPrevented) {\n context.setVisible(false);\n }\n },\n { signal: controller.signal },\n );\n\n form.addEventListener(\n 'submit',\n () => {\n // Always reset the visibility on submit regardless of whether the\n // default action is prevented\n context.setVisible(false);\n },\n { signal: controller.signal },\n );\n\n onCleanup(() => {\n controller.abort();\n });\n });\n\n return (\n <Primitive.input\n {...rest}\n id={local.id ?? context.inputId()}\n autoCapitalize={local.autoCapitalize ?? 'off'}\n autocomplete={local.autocomplete ?? 'current-password'}\n ref={mergeRefs(local.ref, (el: any) => context.setInputRef(el as HTMLInputElement))}\n spellcheck={local.spellcheck ?? false}\n type={context.visible() ? 'text' : 'password'}\n data-state={getVisibilityState(context.visible())}\n onBlur={composeEventHandlers(\n local.onBlur as JSX.EventHandler<HTMLInputElement, FocusEvent>,\n (event) => {\n const { selectionStart, selectionEnd } = event.currentTarget;\n context.focusState.selectionStart = selectionStart;\n context.focusState.selectionEnd = selectionEnd;\n },\n )}\n />\n );\n}\n\n/* -------------------------------------------------------------------------------------------------\n * PasswordToggleFieldToggle\n * -----------------------------------------------------------------------------------------------*/\n\nconst PASSWORD_TOGGLE_FIELD_TOGGLE_NAME = PASSWORD_TOGGLE_FIELD_NAME + 'Toggle';\n\ninterface PasswordToggleFieldToggleProps extends Omit<PrimitiveProps<'button'>, 'type'> {\n __scopePasswordToggleField?: Scope;\n}\n\nfunction PasswordToggleFieldToggle(props: PasswordToggleFieldToggleProps) {\n const [local, rest] = splitProps(props, [\n '__scopePasswordToggleField',\n 'onClick',\n 'onPointerDown',\n 'onPointerCancel',\n 'onPointerUp',\n 'children',\n 'aria-label',\n 'aria-controls',\n 'aria-hidden',\n 'tabIndex',\n 'ref',\n ]);\n\n const context = usePasswordToggleFieldContext(\n PASSWORD_TOGGLE_FIELD_TOGGLE_NAME,\n local.__scopePasswordToggleField,\n );\n\n let elementRef: HTMLButtonElement | undefined;\n\n // Auto-generate aria-label if no text content and no explicit aria-label\n const [internalAriaLabel, setInternalAriaLabel] = createSignal<string | undefined>(undefined);\n\n createEffect(() => {\n const element = elementRef;\n const ariaLabelProp = local['aria-label'];\n if (!element || ariaLabelProp) {\n setInternalAriaLabel(undefined);\n return;\n }\n\n const DEFAULT_ARIA_LABEL = context.visible() ? 'Hide password' : 'Show password';\n\n function checkForInnerTextLabel(textContent: string | undefined | null) {\n const text = textContent ? textContent : undefined;\n setInternalAriaLabel(text ? undefined : DEFAULT_ARIA_LABEL);\n }\n\n checkForInnerTextLabel(element.textContent);\n\n const observer = new MutationObserver((entries) => {\n let textContent: string | undefined;\n for (const entry of entries) {\n if (entry.type === 'characterData') {\n if (element.textContent) {\n textContent = element.textContent;\n }\n }\n }\n checkForInnerTextLabel(textContent);\n });\n observer.observe(element, { characterData: true, subtree: true });\n\n onCleanup(() => {\n observer.disconnect();\n });\n });\n\n const ariaLabel = () => local['aria-label'] || internalAriaLabel();\n\n // Reset clickTriggered on global pointerup\n createEffect(() => {\n const ownerWindow = elementRef?.ownerDocument?.defaultView || window;\n\n let idleCleanup = () => {};\n const reset = () => {\n context.focusState.clickTriggered = false;\n };\n const handlePointerUp = () => {\n idleCleanup = requestIdleCallbackCompat(ownerWindow, reset);\n };\n\n ownerWindow.addEventListener('pointerup', handlePointerUp);\n\n onCleanup(() => {\n idleCleanup();\n ownerWindow.removeEventListener('pointerup', handlePointerUp);\n });\n });\n\n return (\n <Primitive.button\n aria-controls={local['aria-controls'] ?? context.inputId()}\n aria-label={ariaLabel()}\n data-state={getVisibilityState(context.visible())}\n {...rest}\n ref={mergeRefs(local.ref, (el: any) => {\n elementRef = el as HTMLButtonElement;\n })}\n onPointerDown={composeEventHandlers(\n local.onPointerDown as JSX.EventHandler<HTMLButtonElement, PointerEvent>,\n () => {\n context.focusState.clickTriggered = true;\n },\n )}\n on:pointercancel={(event: PointerEvent) => {\n const handler = local.onPointerCancel;\n if (typeof handler === 'function') {\n (handler as any)(event);\n }\n // Always reset focus state on cancellation\n Object.assign(context.focusState, INITIAL_FOCUS_STATE);\n }}\n on:click={(event: MouseEvent) => {\n const handler = local.onClick;\n if (typeof handler === 'function') {\n (handler as any)(event);\n }\n if (event.defaultPrevented) {\n Object.assign(context.focusState, INITIAL_FOCUS_STATE);\n return;\n }\n\n // Toggle visibility synchronously\n batch(() => {\n context.setVisible((prev) => !prev);\n });\n\n if (context.focusState.clickTriggered) {\n const input = context.inputRef();\n if (input) {\n const { selectionStart, selectionEnd } = context.focusState;\n input.focus();\n if (selectionStart !== null || selectionEnd !== null) {\n // Wait a tick so that focus has settled, then restore selection position\n requestAnimationFrame(() => {\n if (input.ownerDocument.activeElement === input) {\n input.selectionStart = selectionStart;\n input.selectionEnd = selectionEnd;\n }\n });\n }\n }\n }\n Object.assign(context.focusState, INITIAL_FOCUS_STATE);\n }}\n on:pointerup={(event: PointerEvent) => {\n const handler = local.onPointerUp;\n if (typeof handler === 'function') {\n (handler as any)(event);\n }\n // If click handler hasn't been called at this point, it may have been\n // intercepted, in which case we still want to reset our internal state\n setTimeout(() => {\n Object.assign(context.focusState, INITIAL_FOCUS_STATE);\n }, 50);\n }}\n type=\"button\"\n >\n {local.children}\n </Primitive.button>\n );\n}\n\n/* -------------------------------------------------------------------------------------------------\n * PasswordToggleFieldSlot\n * -----------------------------------------------------------------------------------------------*/\n\nconst PASSWORD_TOGGLE_FIELD_SLOT_NAME = PASSWORD_TOGGLE_FIELD_NAME + 'Slot';\n\ninterface PasswordToggleFieldSlotDeclarativeProps {\n visible: JSX.Element;\n hidden: JSX.Element;\n __scopePasswordToggleField?: Scope;\n}\n\ninterface PasswordToggleFieldSlotRenderProps {\n render: (args: { visible: boolean }) => JSX.Element;\n __scopePasswordToggleField?: Scope;\n}\n\ntype PasswordToggleFieldSlotProps =\n | PasswordToggleFieldSlotDeclarativeProps\n | PasswordToggleFieldSlotRenderProps;\n\nfunction PasswordToggleFieldSlot(props: PasswordToggleFieldSlotProps) {\n const [local, rest] = splitProps(props as ScopedProps<PasswordToggleFieldSlotProps>, [\n '__scopePasswordToggleField',\n ]);\n\n const context = usePasswordToggleFieldContext(\n PASSWORD_TOGGLE_FIELD_SLOT_NAME,\n local.__scopePasswordToggleField,\n );\n\n if ('render' in rest) {\n return <>{(rest as PasswordToggleFieldSlotRenderProps).render({ visible: context.visible() })}</>;\n }\n\n const declarativeProps = rest as PasswordToggleFieldSlotDeclarativeProps;\n return <>{context.visible() ? declarativeProps.visible : declarativeProps.hidden}</>;\n}\n\n/* -------------------------------------------------------------------------------------------------\n * PasswordToggleFieldIcon\n * -----------------------------------------------------------------------------------------------*/\n\nconst PASSWORD_TOGGLE_FIELD_ICON_NAME = PASSWORD_TOGGLE_FIELD_NAME + 'Icon';\n\ninterface PasswordToggleFieldIconProps extends Omit<PrimitiveProps<'svg'>, 'children'> {\n visible: JSX.Element;\n hidden: JSX.Element;\n __scopePasswordToggleField?: Scope;\n}\n\nfunction PasswordToggleFieldIcon(props: PasswordToggleFieldIconProps) {\n const [local, rest] = splitProps(props, [\n '__scopePasswordToggleField',\n 'visible',\n 'hidden',\n 'ref',\n ]);\n\n const context = usePasswordToggleFieldContext(\n PASSWORD_TOGGLE_FIELD_ICON_NAME,\n local.__scopePasswordToggleField,\n );\n\n return (\n <Primitive.svg\n {...rest}\n ref={local.ref}\n aria-hidden\n asChild\n data-state={getVisibilityState(context.visible())}\n >\n {context.visible() ? local.visible : local.hidden}\n </Primitive.svg>\n );\n}\n\n/* -------------------------------------------------------------------------------------------------\n * Utils\n * -----------------------------------------------------------------------------------------------*/\n\nfunction getVisibilityState(visible: boolean): 'visible' | 'hidden' {\n return visible ? 'visible' : 'hidden';\n}\n\nfunction requestIdleCallbackCompat(\n window: Window,\n callback: IdleRequestCallback,\n options?: IdleRequestOptions,\n): () => void {\n if ((window as any).requestIdleCallback) {\n const id = window.requestIdleCallback(callback, options);\n return () => {\n window.cancelIdleCallback(id);\n };\n }\n const start = Date.now();\n const id = window.setTimeout(() => {\n const timeRemaining = () => Math.max(0, 50 - (Date.now() - start));\n callback({ didTimeout: false, timeRemaining });\n }, 1);\n return () => {\n window.clearTimeout(id);\n };\n}\n\n/* ---------------------------------------------------------------------------------------------- */\n\nconst Root = PasswordToggleField;\nconst Input = PasswordToggleFieldInput;\nconst Toggle = PasswordToggleFieldToggle;\nconst Slot = PasswordToggleFieldSlot;\nconst Icon = PasswordToggleFieldIcon;\n\nexport {\n createPasswordToggleFieldScope,\n //\n PasswordToggleField,\n PasswordToggleFieldInput,\n PasswordToggleFieldToggle,\n PasswordToggleFieldSlot,\n PasswordToggleFieldIcon,\n //\n Root,\n Input,\n Toggle,\n Slot,\n Icon,\n};\nexport type {\n PasswordToggleFieldProps,\n PasswordToggleFieldInputProps,\n PasswordToggleFieldToggleProps,\n PasswordToggleFieldSlotProps,\n PasswordToggleFieldIconProps,\n};\n"]}
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "@radix-solid-js/password-toggle-field",
3
+ "version": "0.1.0",
4
+ "license": "MIT",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": {
12
+ "types": "./dist/index.d.ts",
13
+ "default": "./dist/index.js"
14
+ },
15
+ "require": {
16
+ "types": "./dist/index.d.cts",
17
+ "default": "./dist/index.cjs"
18
+ }
19
+ }
20
+ },
21
+ "files": [
22
+ "dist"
23
+ ],
24
+ "sideEffects": false,
25
+ "scripts": {
26
+ "build": "tsup",
27
+ "clean": "rm -rf dist",
28
+ "typecheck": "tsc --noEmit",
29
+ "test": "vitest run"
30
+ },
31
+ "dependencies": {
32
+ "@radix-solid-js/primitive": "workspace:*",
33
+ "@radix-solid-js/compose-refs": "workspace:*",
34
+ "@radix-solid-js/context": "workspace:*",
35
+ "@radix-solid-js/id": "workspace:*",
36
+ "@radix-solid-js/primitive-component": "workspace:*",
37
+ "@radix-solid-js/use-controllable-state": "workspace:*",
38
+ "@radix-solid-js/use-effect-event": "workspace:*"
39
+ },
40
+ "peerDependencies": {
41
+ "solid-js": "^1.8.0"
42
+ },
43
+ "devDependencies": {
44
+ "@repo/tsconfig": "workspace:*",
45
+ "tsup": "^8.3.6",
46
+ "typescript": "^5.7.3",
47
+ "solid-js": "^1.9.3",
48
+ "vitest": "^2.1.8"
49
+ },
50
+ "publishConfig": {
51
+ "access": "public"
52
+ },
53
+ "repository": {
54
+ "type": "git",
55
+ "url": "https://github.com/ljho01/shadcn-solid-js.git",
56
+ "directory": "packages/solid/password-toggle-field"
57
+ }
58
+ }