@ews-admin/global-design-system 1.29.0 → 1.30.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.
Files changed (35) hide show
  1. package/dist/components/LockScreen/LockScreen.d.ts +12 -0
  2. package/dist/components/LockScreen/LockScreen.d.ts.map +1 -0
  3. package/dist/components/LockScreen/LockScreen.types.d.ts +65 -0
  4. package/dist/components/LockScreen/LockScreen.types.d.ts.map +1 -0
  5. package/dist/components/LockScreen/index.d.ts +3 -0
  6. package/dist/components/LockScreen/index.d.ts.map +1 -0
  7. package/dist/components/PinPad/PinPad.d.ts +10 -0
  8. package/dist/components/PinPad/PinPad.d.ts.map +1 -0
  9. package/dist/components/PinPad/PinPad.types.d.ts +24 -0
  10. package/dist/components/PinPad/PinPad.types.d.ts.map +1 -0
  11. package/dist/components/PinPad/index.d.ts +3 -0
  12. package/dist/components/PinPad/index.d.ts.map +1 -0
  13. package/dist/hooks/index.d.ts +2 -0
  14. package/dist/hooks/index.d.ts.map +1 -1
  15. package/dist/hooks/useIdleLock.d.ts +24 -0
  16. package/dist/hooks/useIdleLock.d.ts.map +1 -0
  17. package/dist/index.css +1 -1
  18. package/dist/index.d.ts +128 -2
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.esm.css +1 -1
  21. package/dist/index.esm.js +375 -1
  22. package/dist/index.esm.js.map +1 -1
  23. package/dist/index.js +377 -0
  24. package/dist/index.js.map +1 -1
  25. package/package.json +1 -1
  26. package/src/components/LockScreen/LockScreen.tsx +324 -0
  27. package/src/components/LockScreen/LockScreen.types.ts +67 -0
  28. package/src/components/LockScreen/index.ts +6 -0
  29. package/src/components/PinPad/PinPad.tsx +150 -0
  30. package/src/components/PinPad/PinPad.types.ts +23 -0
  31. package/src/components/PinPad/index.ts +2 -0
  32. package/src/hooks/index.ts +2 -0
  33. package/src/hooks/useIdleLock.ts +181 -0
  34. package/src/index.ts +21 -2
  35. package/tailwind.preset.js +11 -0
package/dist/index.js CHANGED
@@ -33083,6 +33083,155 @@ function useDebouncedCallback(callback, delay) {
33083
33083
  return debouncedCallback;
33084
33084
  }
33085
33085
 
33086
+ const DEFAULT_TIMEOUT_MS = 180000;
33087
+ const DEFAULT_STORAGE_KEY = "ews-idle-lock";
33088
+ const ACTIVITY_WRITE_INTERVAL_MS = 5000;
33089
+ const ACTIVITY_EVENTS = [
33090
+ "pointerdown",
33091
+ "pointermove",
33092
+ "keydown",
33093
+ "wheel",
33094
+ "scroll",
33095
+ "touchstart",
33096
+ ];
33097
+ const readStorage = (key) => {
33098
+ try {
33099
+ return typeof window === "undefined" ? null : window.localStorage.getItem(key);
33100
+ }
33101
+ catch {
33102
+ return null;
33103
+ }
33104
+ };
33105
+ const writeStorage = (key, value) => {
33106
+ try {
33107
+ if (typeof window === "undefined")
33108
+ return;
33109
+ if (value === null)
33110
+ window.localStorage.removeItem(key);
33111
+ else
33112
+ window.localStorage.setItem(key, value);
33113
+ }
33114
+ catch {
33115
+ // Storage unavailable (private mode, quota): the lock still works in this tab.
33116
+ }
33117
+ };
33118
+ /**
33119
+ * Locks the screen after `timeoutMs` without user activity. The locked flag is
33120
+ * kept in localStorage (it survives a reload) and shared between tabs through
33121
+ * a BroadcastChannel, or the `storage` event where BroadcastChannel is missing:
33122
+ * locking or unlocking one tab does the same in every tab. Activity in any tab
33123
+ * keeps every tab unlocked.
33124
+ */
33125
+ function useIdleLock({ timeoutMs = DEFAULT_TIMEOUT_MS, onLock, storageKey = DEFAULT_STORAGE_KEY, enabled = true, } = {}) {
33126
+ const activityKey = `${storageKey}:activity`;
33127
+ const [locked, setLocked] = React.useState(() => readStorage(storageKey) === "1");
33128
+ const lockedRef = React.useRef(locked);
33129
+ const onLockRef = React.useRef(onLock);
33130
+ const lastActivity = React.useRef(Date.now());
33131
+ const lastActivityWrite = React.useRef(0);
33132
+ const channelRef = React.useRef(null);
33133
+ React.useEffect(() => {
33134
+ onLockRef.current = onLock;
33135
+ }, [onLock]);
33136
+ const markActivity = React.useCallback((now) => {
33137
+ lastActivity.current = now;
33138
+ if (now - lastActivityWrite.current >= ACTIVITY_WRITE_INTERVAL_MS) {
33139
+ lastActivityWrite.current = now;
33140
+ writeStorage(activityKey, String(now));
33141
+ }
33142
+ }, [activityKey]);
33143
+ const applyLocked = React.useCallback((next) => {
33144
+ if (lockedRef.current === next)
33145
+ return;
33146
+ lockedRef.current = next;
33147
+ setLocked(next);
33148
+ if (next)
33149
+ onLockRef.current?.();
33150
+ }, []);
33151
+ const lock = React.useCallback(() => {
33152
+ if (lockedRef.current)
33153
+ return;
33154
+ writeStorage(storageKey, "1");
33155
+ channelRef.current?.postMessage("lock");
33156
+ applyLocked(true);
33157
+ }, [storageKey, applyLocked]);
33158
+ const unlock = React.useCallback(() => {
33159
+ lastActivityWrite.current = 0;
33160
+ markActivity(Date.now());
33161
+ writeStorage(storageKey, null);
33162
+ channelRef.current?.postMessage("unlock");
33163
+ applyLocked(false);
33164
+ }, [storageKey, applyLocked, markActivity]);
33165
+ // Cross-tab sync.
33166
+ React.useEffect(() => {
33167
+ if (typeof window === "undefined")
33168
+ return;
33169
+ const onRemote = (nextLocked) => {
33170
+ if (!nextLocked)
33171
+ lastActivity.current = Date.now();
33172
+ applyLocked(nextLocked);
33173
+ };
33174
+ if (typeof window.BroadcastChannel === "function") {
33175
+ const channel = new window.BroadcastChannel(storageKey);
33176
+ channelRef.current = channel;
33177
+ channel.onmessage = (event) => {
33178
+ if (event.data === "lock")
33179
+ onRemote(true);
33180
+ else if (event.data === "unlock")
33181
+ onRemote(false);
33182
+ };
33183
+ return () => {
33184
+ channelRef.current = null;
33185
+ channel.close();
33186
+ };
33187
+ }
33188
+ const onStorage = (event) => {
33189
+ if (event.key !== storageKey)
33190
+ return;
33191
+ onRemote(event.newValue === "1");
33192
+ };
33193
+ window.addEventListener("storage", onStorage);
33194
+ return () => window.removeEventListener("storage", onStorage);
33195
+ }, [storageKey, applyLocked]);
33196
+ // Inactivity timer.
33197
+ React.useEffect(() => {
33198
+ if (!enabled || locked || typeof window === "undefined")
33199
+ return;
33200
+ lastActivity.current = Date.now();
33201
+ let timer;
33202
+ const idleFor = () => {
33203
+ const shared = Number(readStorage(activityKey)) || 0;
33204
+ return Date.now() - Math.max(lastActivity.current, shared);
33205
+ };
33206
+ const check = () => {
33207
+ const idle = idleFor();
33208
+ if (idle >= timeoutMs)
33209
+ lock();
33210
+ else
33211
+ timer = setTimeout(check, timeoutMs - idle);
33212
+ };
33213
+ const onActivity = () => markActivity(Date.now());
33214
+ // Timers are throttled in background tabs: check the delay on return.
33215
+ const onVisibility = () => {
33216
+ if (document.visibilityState !== "visible")
33217
+ return;
33218
+ if (idleFor() >= timeoutMs)
33219
+ lock();
33220
+ else
33221
+ onActivity();
33222
+ };
33223
+ timer = setTimeout(check, timeoutMs);
33224
+ ACTIVITY_EVENTS.forEach((name) => document.addEventListener(name, onActivity, { capture: true, passive: true }));
33225
+ document.addEventListener("visibilitychange", onVisibility);
33226
+ return () => {
33227
+ clearTimeout(timer);
33228
+ ACTIVITY_EVENTS.forEach((name) => document.removeEventListener(name, onActivity, { capture: true }));
33229
+ document.removeEventListener("visibilitychange", onVisibility);
33230
+ };
33231
+ }, [enabled, locked, timeoutMs, activityKey, lock, markActivity]);
33232
+ return { locked, lock, unlock };
33233
+ }
33234
+
33086
33235
  function useSelectField({ name, control, options: _options, rules, defaultValue, }) {
33087
33236
  const { field, fieldState: { error, invalid }, } = reactHookForm.useController({
33088
33237
  name,
@@ -35292,6 +35441,231 @@ const PaymentDueBanner = ({ title, subtitle, warning, ctaLabel, onCtaClick, onDi
35292
35441
  */
35293
35442
  const SecureLoader = ({ label, description }) => (jsxRuntime.jsx("div", { "data-testid": "secure-loader", className: "flex min-h-screen items-center justify-center bg-gray-100", children: jsxRuntime.jsxs("div", { className: "flex flex-col items-center rounded-lg bg-white p-6 shadow-lg", children: [jsxRuntime.jsxs("div", { className: "relative", children: [jsxRuntime.jsx(Lock, { className: "h-16 w-16 text-gray-500" }), jsxRuntime.jsx("div", { className: "absolute bottom-2 right-1 h-6 w-6 animate-spin rounded-full border-4 border-gray-300 border-t-green-500" })] }), jsxRuntime.jsx("p", { className: "mt-4 text-lg text-gray-600", children: label }), description && (jsxRuntime.jsx("p", { className: "mt-2 text-sm text-gray-500", children: description }))] }) }));
35294
35443
 
35444
+ const DIGIT_ROWS = ["1", "2", "3", "4", "5", "6", "7", "8", "9"];
35445
+ const keyClass = "flex h-16 w-16 items-center justify-center justify-self-center rounded-full text-3xl font-light text-ews-gray-900 " +
35446
+ "transition-colors hover:bg-ews-gray-100 active:bg-ews-gray-200 " +
35447
+ "focus-visible:ring-2 focus-visible:ring-ews-primary disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:bg-transparent";
35448
+ /**
35449
+ * iOS-style PIN entry: a row of dots filled as digits are typed and a 3x4
35450
+ * keypad. Texts are provided by the caller (already translated).
35451
+ */
35452
+ const PinPad = ({ length = 4, onComplete, onChange, disabled = false, invalid = false, resetKey, captureKeyboard = true, eraseLabel, progressLabel, keypadLabel, className, }) => {
35453
+ const [value, setValue] = React.useState("");
35454
+ const valueRef = React.useRef("");
35455
+ const update = React.useCallback((next) => {
35456
+ valueRef.current = next;
35457
+ setValue(next);
35458
+ onChange?.(next);
35459
+ if (next.length === length)
35460
+ onComplete(next);
35461
+ }, [length, onChange, onComplete]);
35462
+ // Clear the typed digits when the caller asks for it.
35463
+ React.useEffect(() => {
35464
+ valueRef.current = "";
35465
+ setValue("");
35466
+ }, [resetKey]);
35467
+ const press = React.useCallback((digit) => {
35468
+ if (disabled || valueRef.current.length >= length)
35469
+ return;
35470
+ update(valueRef.current + digit);
35471
+ }, [disabled, length, update]);
35472
+ const erase = React.useCallback(() => {
35473
+ if (disabled || valueRef.current.length === 0)
35474
+ return;
35475
+ update(valueRef.current.slice(0, -1));
35476
+ }, [disabled, update]);
35477
+ React.useEffect(() => {
35478
+ if (!captureKeyboard)
35479
+ return;
35480
+ const onKeyDown = (event) => {
35481
+ if (event.ctrlKey || event.metaKey || event.altKey)
35482
+ return;
35483
+ const target = event.target;
35484
+ if (target && (target.tagName === "INPUT" || target.tagName === "TEXTAREA"))
35485
+ return;
35486
+ if (/^[0-9]$/.test(event.key)) {
35487
+ event.preventDefault();
35488
+ press(event.key);
35489
+ }
35490
+ else if (event.key === "Backspace") {
35491
+ event.preventDefault();
35492
+ erase();
35493
+ }
35494
+ };
35495
+ document.addEventListener("keydown", onKeyDown);
35496
+ return () => document.removeEventListener("keydown", onKeyDown);
35497
+ }, [captureKeyboard, press, erase]);
35498
+ return (jsxRuntime.jsxs("div", { className: cn("flex flex-col items-center gap-10", className), children: [jsxRuntime.jsx("div", { dir: "ltr", "aria-hidden": "true", "data-testid": "pin-dots", className: cn("flex gap-5", invalid && "animate-pin-shake"), children: Array.from({ length }, (_, index) => (jsxRuntime.jsx("span", { "data-filled": index < value.length, className: cn("h-3.5 w-3.5 rounded-full transition-colors", invalid
35499
+ ? "bg-ews-error"
35500
+ : index < value.length
35501
+ ? "bg-ews-primary"
35502
+ : "bg-ews-primary-light", disabled && index < value.length && "animate-pulse") }, index))) }), jsxRuntime.jsx("p", { className: "sr-only", "aria-live": "polite", "aria-atomic": "true", children: progressLabel(value.length, length) }), jsxRuntime.jsxs("div", { dir: "ltr", role: "group", "aria-label": keypadLabel, className: "grid grid-cols-3 gap-x-8 gap-y-4", children: [DIGIT_ROWS.map((digit) => (jsxRuntime.jsx("button", { type: "button", className: keyClass, disabled: disabled, onClick: () => press(digit), children: digit }, digit))), jsxRuntime.jsx("span", { "aria-hidden": "true" }), jsxRuntime.jsx("button", { type: "button", className: keyClass, disabled: disabled, onClick: () => press("0"), children: "0" }), jsxRuntime.jsx("button", { type: "button", className: cn(keyClass, "text-ews-gray-700"), disabled: disabled || value.length === 0, "aria-label": eraseLabel, onClick: erase, children: jsxRuntime.jsx(Delete, { className: "h-7 w-7", strokeWidth: 1.5, "aria-hidden": "true" }) })] })] }));
35503
+ };
35504
+
35505
+ const FIRST_STEP = {
35506
+ create: "new",
35507
+ unlock: "unlock",
35508
+ change: "current",
35509
+ reset: "otp",
35510
+ };
35511
+ const titleOf = (mode, step, texts) => {
35512
+ switch (step) {
35513
+ case "unlock":
35514
+ return texts.unlockTitle;
35515
+ case "current":
35516
+ return texts.currentTitle;
35517
+ case "otp":
35518
+ return texts.otpTitle;
35519
+ case "new":
35520
+ return mode === "create" ? texts.createTitle : texts.newTitle;
35521
+ case "confirm":
35522
+ return texts.confirmTitle;
35523
+ }
35524
+ };
35525
+ const FOCUSABLE = 'button:not([disabled]), input:not([disabled]), a[href], [tabindex]:not([tabindex="-1"])';
35526
+ /**
35527
+ * Blocking PIN screen: creates, checks, changes or resets (with a one-time
35528
+ * code) the user's secret code. Full screen on mobile, centered card on a grey
35529
+ * backdrop from 640px. Submit handlers return promises: a rejection clears the
35530
+ * code and goes back to the first step, the app shows its message in `error`.
35531
+ */
35532
+ const LockScreen = ({ mode, texts, error, busy = false, onCreate, onUnlock, onChangePin, onReset, onForgot, onCancel, pinLength = 4, otpLength = 6, logo, className, }) => {
35533
+ const [step, setStep] = React.useState(FIRST_STEP[mode]);
35534
+ const [firstValue, setFirstValue] = React.useState(""); // current PIN or one-time code
35535
+ const [newPin, setNewPin] = React.useState("");
35536
+ const [otp, setOtp] = React.useState("");
35537
+ const [localError, setLocalError] = React.useState(null);
35538
+ const [invalid, setInvalid] = React.useState(false);
35539
+ const [pending, setPending] = React.useState(false);
35540
+ const [resetKey, setResetKey] = React.useState(0);
35541
+ const panelRef = React.useRef(null);
35542
+ const mounted = React.useRef(true);
35543
+ const restart = React.useCallback((failed) => {
35544
+ setStep(FIRST_STEP[mode]);
35545
+ setFirstValue("");
35546
+ setNewPin("");
35547
+ setOtp("");
35548
+ setInvalid(failed);
35549
+ setResetKey((key) => key + 1);
35550
+ }, [mode]);
35551
+ React.useEffect(() => {
35552
+ restart(false);
35553
+ setLocalError(null);
35554
+ }, [restart]);
35555
+ React.useEffect(() => {
35556
+ mounted.current = true;
35557
+ return () => {
35558
+ mounted.current = false;
35559
+ };
35560
+ }, []);
35561
+ // Block page scroll and keep focus inside the screen.
35562
+ React.useEffect(() => {
35563
+ const previousOverflow = document.body.style.overflow;
35564
+ document.body.style.overflow = "hidden";
35565
+ const previousFocus = document.activeElement;
35566
+ panelRef.current?.focus();
35567
+ const keepFocus = (event) => {
35568
+ const panel = panelRef.current;
35569
+ if (panel && !panel.contains(event.target))
35570
+ panel.focus();
35571
+ };
35572
+ document.addEventListener("focusin", keepFocus);
35573
+ return () => {
35574
+ document.body.style.overflow = previousOverflow;
35575
+ document.removeEventListener("focusin", keepFocus);
35576
+ previousFocus?.focus?.();
35577
+ };
35578
+ }, []);
35579
+ const trapTab = (event) => {
35580
+ if (event.key !== "Tab" || !panelRef.current)
35581
+ return;
35582
+ const items = Array.from(panelRef.current.querySelectorAll(FOCUSABLE));
35583
+ if (items.length === 0) {
35584
+ event.preventDefault();
35585
+ return;
35586
+ }
35587
+ const first = items[0];
35588
+ const last = items[items.length - 1];
35589
+ const active = document.activeElement;
35590
+ if (event.shiftKey && (active === first || active === panelRef.current)) {
35591
+ event.preventDefault();
35592
+ last.focus();
35593
+ }
35594
+ else if (!event.shiftKey && active === last) {
35595
+ event.preventDefault();
35596
+ first.focus();
35597
+ }
35598
+ };
35599
+ const submit = async (call) => {
35600
+ if (!call)
35601
+ return;
35602
+ setPending(true);
35603
+ try {
35604
+ await call();
35605
+ if (mounted.current)
35606
+ restart(false);
35607
+ }
35608
+ catch {
35609
+ if (mounted.current)
35610
+ restart(true);
35611
+ }
35612
+ finally {
35613
+ if (mounted.current)
35614
+ setPending(false);
35615
+ }
35616
+ };
35617
+ const handlePin = (pin) => {
35618
+ setLocalError(null);
35619
+ switch (step) {
35620
+ case "unlock":
35621
+ void submit(onUnlock && (() => onUnlock(pin)));
35622
+ return;
35623
+ case "current":
35624
+ setFirstValue(pin);
35625
+ setStep("new");
35626
+ return;
35627
+ case "new":
35628
+ setNewPin(pin);
35629
+ setStep("confirm");
35630
+ return;
35631
+ case "confirm":
35632
+ if (pin !== newPin) {
35633
+ setLocalError(texts.mismatchError);
35634
+ setInvalid(true);
35635
+ setNewPin("");
35636
+ setStep("new");
35637
+ setResetKey((key) => key + 1);
35638
+ return;
35639
+ }
35640
+ if (mode === "create")
35641
+ void submit(onCreate && (() => onCreate(pin)));
35642
+ else if (mode === "change")
35643
+ void submit(onChangePin && (() => onChangePin(firstValue, pin)));
35644
+ else if (mode === "reset")
35645
+ void submit(onReset && (() => onReset(firstValue, pin)));
35646
+ return;
35647
+ }
35648
+ };
35649
+ const submitOtp = (event) => {
35650
+ event.preventDefault();
35651
+ if (otp.length !== otpLength)
35652
+ return;
35653
+ setFirstValue(otp);
35654
+ setInvalid(false);
35655
+ setStep("new");
35656
+ };
35657
+ const isBusy = busy || pending;
35658
+ const shownError = localError ?? error;
35659
+ const showForgot = !!onForgot &&
35660
+ !!texts.forgot &&
35661
+ (step === "unlock" || step === "current");
35662
+ const title = titleOf(mode, step, texts);
35663
+ return (jsxRuntime.jsx("div", { className: cn("fixed inset-0 z-[1000] flex justify-center overflow-y-auto bg-white", "sm:items-center sm:bg-ews-gray-900/50 sm:backdrop-blur-sm", className), "data-testid": "lock-screen", children: jsxRuntime.jsxs("div", { ref: panelRef, role: "dialog", "aria-modal": "true", "aria-label": texts.dialogLabel, "aria-busy": isBusy, tabIndex: -1, onKeyDown: trapTab, className: cn("flex min-h-full w-full flex-col items-center px-6 pb-8 outline-none", "sm:min-h-0 sm:w-auto sm:min-w-[22rem] sm:rounded-2xl sm:bg-white sm:px-10 sm:py-10 sm:shadow-xl"), children: [jsxRuntime.jsx("div", { className: "flex min-h-[33vh] shrink-0 items-center justify-center sm:min-h-0 sm:pb-8", children: logo ?? jsxRuntime.jsx(Logo, { size: "lg", variant: "normal" }) }), title && (jsxRuntime.jsx("h2", { className: "mb-8 text-center text-lg font-normal text-ews-gray-900", children: title })), step === "otp" ? (jsxRuntime.jsxs("form", { onSubmit: submitOtp, className: "flex w-full max-w-xs flex-col items-center gap-4", children: [texts.otpDescription && (jsxRuntime.jsx("p", { className: "text-center text-sm text-ews-gray-600", children: texts.otpDescription })), jsxRuntime.jsx("label", { className: "sr-only", htmlFor: "lock-screen-otp", children: texts.otpLabel }), jsxRuntime.jsx("input", { id: "lock-screen-otp", dir: "ltr", inputMode: "numeric", autoComplete: "one-time-code", maxLength: otpLength, value: otp, disabled: isBusy, "aria-label": texts.otpLabel, "aria-invalid": invalid || undefined, onChange: (event) => {
35664
+ setOtp(event.target.value.replace(/\D/g, "").slice(0, otpLength));
35665
+ setInvalid(false);
35666
+ }, className: cn("w-full rounded-lg border bg-white px-4 py-3 text-center text-2xl tracking-[0.5em]", "focus:border-ews-primary focus:ring-2 focus:ring-ews-primary", invalid ? "border-ews-error" : "border-ews-gray-300") }), jsxRuntime.jsx(Button, { type: "submit", variant: "ews-primary", fullWidth: true, disabled: otp.length !== otpLength || isBusy, children: texts.otpSubmit })] })) : (jsxRuntime.jsx(PinPad, { length: pinLength, onComplete: handlePin, onChange: () => setInvalid(false), disabled: isBusy, invalid: invalid, resetKey: resetKey, eraseLabel: texts.erase, progressLabel: texts.progress, keypadLabel: texts.keypad }, step)), jsxRuntime.jsx("p", { role: "alert", className: "mt-6 min-h-[1.25rem] text-center text-sm text-ews-error", children: shownError }), jsxRuntime.jsxs("div", { className: "mt-auto flex flex-col items-center gap-3 pt-6 sm:mt-4", children: [showForgot && (jsxRuntime.jsx("button", { type: "button", onClick: onForgot, disabled: isBusy, className: "text-base font-medium text-ews-primary hover:underline focus-visible:underline", children: texts.forgot })), onCancel && texts.cancel && (jsxRuntime.jsx("button", { type: "button", onClick: onCancel, disabled: isBusy, className: "text-sm text-ews-gray-600 hover:underline focus-visible:underline", children: texts.cancel }))] })] }) }));
35667
+ };
35668
+
35295
35669
  const SpecialtySearchAutocomplete = ({ selectedSpecialties = [], onSpecialtiesChange, specialties: availableSpecialties, placeholder = "Search and select medical specialties...", className = "", disabled = false, maxSelections, showSelectedCount = true, title = "Medical Specialties", label = "Select Specialties", getSelectedCountText, removeSpecialtyLabel = "Remove specialty", }) => {
35296
35670
  const [filteredSpecialties, setFilteredSpecialties] = React.useState([]);
35297
35671
  const [isLoading, setIsLoading] = React.useState(false);
@@ -37406,6 +37780,7 @@ exports.LockKeyholeOpen = LockKeyholeOpen;
37406
37780
  exports.LockKeyholeOpenIcon = LockKeyholeOpen;
37407
37781
  exports.LockOpen = LockOpen;
37408
37782
  exports.LockOpenIcon = LockOpen;
37783
+ exports.LockScreen = LockScreen;
37409
37784
  exports.LogIn = LogIn;
37410
37785
  exports.LogInIcon = LogIn;
37411
37786
  exports.LogOut = LogOut;
@@ -39791,6 +40166,7 @@ exports.Pin = Pin;
39791
40166
  exports.PinIcon = Pin;
39792
40167
  exports.PinOff = PinOff;
39793
40168
  exports.PinOffIcon = PinOff;
40169
+ exports.PinPad = PinPad;
39794
40170
  exports.Pipette = Pipette;
39795
40171
  exports.PipetteIcon = Pipette;
39796
40172
  exports.Pizza = Pizza;
@@ -40964,6 +41340,7 @@ exports.isValidPhoneNumber = isValidPhoneNumber;
40964
41340
  exports.parseDateSafe = parseDateSafe;
40965
41341
  exports.useDebounce = useDebounce;
40966
41342
  exports.useDebouncedCallback = useDebouncedCallback;
41343
+ exports.useIdleLock = useIdleLock;
40967
41344
  exports.useSelectField = useSelectField;
40968
41345
  exports.useTheme = useTheme;
40969
41346
  //# sourceMappingURL=index.js.map