From 3f7f7e50694706d7703234cd7110c1e463bcae3c Mon Sep 17 00:00:00 2001 From: HeavenVR Date: Thu, 25 Jun 2026 16:19:58 +0200 Subject: [PATCH 1/3] Consume @openshock/svelte-core; drop duplicated UI/components/utils/theme Migrate the frontend onto the shared @openshock/svelte-core library: - shadcn-svelte ui/ now imported via the $hadcn alias; local ui/ tree removed - shared components (Code, Keyboard, metadata, svg, datetime-picker, dialog-manager, input fields, etc.) and modules (cn, pure utils, type guards, validators, shared types, is-mobile, pwned-passwords) now from $core; local copies deleted - LightSwitch and PasswordInput rewired to the library's decoupled APIs (injected color-scheme; forgotHref/onPwnedCheckError) - design-system theme via @import '@openshock/svelte-core/theme.css' - add $core and $hadcn aliases pointing at the package's dist App-coupled code (ControlModules, shares, Turnstile, errorGuards, usernameValidator, etc.) stays local. --- components.json | 16 -- package.json | 1 + pnpm-lock.yaml | 50 ++++ pnpm-workspace.yaml | 1 + scripts/update-shadcn.js | 103 ------- src/app.css | 251 +----------------- src/lib/api/firmwareCDN.ts | 2 +- .../api/next/transformers/LoginOkResponse.ts | 3 +- .../api/next/transformers/OAuthSignupData.ts | 3 +- src/lib/api/pwnedPasswords.ts | 34 --- src/lib/components/Code.svelte | 13 - src/lib/components/ConfirmDeleteDialog.svelte | 36 --- src/lib/components/Container.svelte | 20 -- .../ControlModules/LiveButton.svelte | 4 +- .../ControlModules/LiveControlModule.svelte | 4 +- .../PublicShareClassicControlModule.svelte | 3 +- .../ControlModules/RichControlModule.svelte | 2 +- .../SharedShockerControlModule.svelte | 2 +- .../ControlModules/ShockerCard.svelte | 2 +- .../ControlModules/SimpleControlHeader.svelte | 2 +- .../dialogs/dialog-shocker-add.svelte | 14 +- .../ControlModules/impl/ActionButtons.svelte | 6 +- .../ControlModules/impl/CircleSlider.svelte | 4 +- .../ControlModules/impl/LimitsDisplay.svelte | 2 +- .../ControlModules/impl/PauseOverlay.svelte | 4 +- .../ControlModules/impl/ShockerMenu.svelte | 8 +- .../impl/ShockerPauseButton.svelte | 4 +- src/lib/components/CopyInput.svelte | 54 ---- src/lib/components/DotGrid.svelte | 51 ---- src/lib/components/EmptyState.svelte | 43 --- src/lib/components/ExpirationPicker.svelte | 8 +- .../components/FirmwareChannelSelector.svelte | 2 +- src/lib/components/Keyboard.svelte | 15 -- src/lib/components/LightSwitch.svelte | 95 ------- src/lib/components/PageHeader.svelte | 33 --- src/lib/components/Stepper.svelte | 2 +- src/lib/components/Table/CellContent.svelte | 4 +- src/lib/components/Table/ColumnUtils.ts | 11 +- .../components/Table/DataTableTemplate.svelte | 6 +- .../components/Table/PaginationFooter.svelte | 10 +- src/lib/components/TableActionMenu.svelte | 26 -- .../components/TelemetryConsentToast.svelte | 2 +- src/lib/components/Turnstile.svelte | 4 +- src/lib/components/auth/oauth-buttons.svelte | 10 +- .../datetime-picker/date-time-picker.svelte | 87 ------ .../datetime-picker/time-picker-input.svelte | 140 ---------- .../datetime-picker/time-picker-utils.ts | 190 ------------- .../datetime-picker/time-picker.svelte | 83 ------ .../dialog-alert-content.svelte | 21 -- .../dialog-confirm-content.svelte | 45 ---- .../dialog-custom-content.svelte | 16 -- .../dialog-manager/dialog-manager.svelte | 35 --- .../dialog-manager/dialog-store.svelte.ts | 96 ------- src/lib/components/dialog-manager/types.ts | 59 ---- src/lib/components/input/DatePicker.svelte | 8 +- src/lib/components/input/EmailInput.svelte | 51 ---- src/lib/components/input/PasswordInput.svelte | 161 ----------- src/lib/components/input/TextInput.svelte | 130 --------- src/lib/components/input/UsernameInput.svelte | 8 +- .../components/input/impl/ButtonSettings.ts | 2 +- .../input/impl/PasswordStrengthMeter.svelte | 35 --- src/lib/components/metadata/BasicTags.svelte | 15 -- .../components/metadata/OpenGraphTags.svelte | 106 -------- .../metadata/Twitter/TwitterAppTags.svelte | 32 --- .../metadata/Twitter/TwitterPlayerTags.svelte | 44 --- .../Twitter/TwitterSummaryTags.svelte | 42 --- src/lib/components/metadata/Twitter/index.ts | 5 - src/lib/components/metadata/index.ts | 5 - .../shares/permission-tooltip.svelte | 2 +- .../shares/restrictions-selector.svelte | 8 +- .../components/shares/user-selector.svelte | 6 +- src/lib/components/svg/ChromeLogo.svelte | 73 ----- src/lib/components/svg/CloudflareLogo.svelte | 72 ----- src/lib/components/svg/DiscordLogo.svelte | 24 -- src/lib/components/svg/EdgeLogo.svelte | 126 --------- src/lib/components/svg/GithubIcon.svelte | 24 -- src/lib/components/svg/GoogleLogo.svelte | 24 -- src/lib/components/svg/LiveControlIcon.svelte | 2 +- src/lib/components/svg/OperaLogo.svelte | 54 ---- src/lib/components/svg/XLogo.svelte | 24 -- src/lib/components/ui/README.md | 47 ---- .../ui/accordion/accordion-content.svelte | 27 -- .../ui/accordion/accordion-item.svelte | 17 -- .../ui/accordion/accordion-trigger.svelte | 32 --- .../components/ui/accordion/accordion.svelte | 19 -- src/lib/components/ui/accordion/index.ts | 16 -- .../components/ui/avatar/avatar-badge.svelte | 26 -- .../ui/avatar/avatar-fallback.svelte | 20 -- .../ui/avatar/avatar-group-count.svelte | 23 -- .../components/ui/avatar/avatar-group.svelte | 23 -- .../components/ui/avatar/avatar-image.svelte | 17 -- src/lib/components/ui/avatar/avatar.svelte | 26 -- src/lib/components/ui/avatar/index.ts | 22 -- src/lib/components/ui/badge/badge.svelte | 49 ---- src/lib/components/ui/badge/index.ts | 2 - .../ui/breadcrumb/breadcrumb-ellipsis.svelte | 23 -- .../ui/breadcrumb/breadcrumb-item.svelte | 20 -- .../ui/breadcrumb/breadcrumb-link.svelte | 31 --- .../ui/breadcrumb/breadcrumb-list.svelte | 20 -- .../ui/breadcrumb/breadcrumb-page.svelte | 23 -- .../ui/breadcrumb/breadcrumb-separator.svelte | 27 -- .../ui/breadcrumb/breadcrumb.svelte | 22 -- src/lib/components/ui/breadcrumb/index.ts | 25 -- src/lib/components/ui/button/button.svelte | 82 ------ src/lib/components/ui/button/index.ts | 17 -- .../ui/calendar/calendar-caption.svelte | 76 ------ .../ui/calendar/calendar-cell.svelte | 19 -- .../ui/calendar/calendar-day.svelte | 33 --- .../ui/calendar/calendar-grid-body.svelte | 12 - .../ui/calendar/calendar-grid-head.svelte | 12 - .../ui/calendar/calendar-grid-row.svelte | 12 - .../ui/calendar/calendar-grid.svelte | 16 -- .../ui/calendar/calendar-head-cell.svelte | 19 -- .../ui/calendar/calendar-header.svelte | 19 -- .../ui/calendar/calendar-heading.svelte | 16 -- .../ui/calendar/calendar-month-select.svelte | 48 ---- .../ui/calendar/calendar-month.svelte | 15 -- .../ui/calendar/calendar-months.svelte | 19 -- .../ui/calendar/calendar-nav.svelte | 19 -- .../ui/calendar/calendar-next-button.svelte | 36 --- .../ui/calendar/calendar-prev-button.svelte | 36 --- .../ui/calendar/calendar-year-select.svelte | 47 ---- .../components/ui/calendar/calendar.svelte | 115 -------- src/lib/components/ui/calendar/index.ts | 40 --- src/lib/components/ui/card/card-action.svelte | 23 -- .../components/ui/card/card-content.svelte | 20 -- .../ui/card/card-description.svelte | 20 -- src/lib/components/ui/card/card-footer.svelte | 20 -- src/lib/components/ui/card/card-header.svelte | 23 -- src/lib/components/ui/card/card-title.svelte | 20 -- src/lib/components/ui/card/card.svelte | 22 -- src/lib/components/ui/card/index.ts | 25 -- .../components/ui/checkbox/checkbox.svelte | 39 --- src/lib/components/ui/checkbox/index.ts | 6 - .../ui/collapsible/collapsible-content.svelte | 7 - .../ui/collapsible/collapsible-trigger.svelte | 7 - .../ui/collapsible/collapsible.svelte | 11 - src/lib/components/ui/collapsible/index.ts | 13 - .../ui/command/command-dialog.svelte | 42 --- .../ui/command/command-empty.svelte | 17 -- .../ui/command/command-group.svelte | 32 --- .../ui/command/command-input.svelte | 34 --- .../components/ui/command/command-item.svelte | 25 -- .../ui/command/command-link-item.svelte | 20 -- .../components/ui/command/command-list.svelte | 17 -- .../ui/command/command-loading.svelte | 7 - .../ui/command/command-separator.svelte | 17 -- .../ui/command/command-shortcut.svelte | 20 -- src/lib/components/ui/command/command.svelte | 25 -- src/lib/components/ui/command/index.ts | 37 --- .../ui/data-table/data-table.svelte.ts | 142 ---------- .../ui/data-table/flex-render.svelte | 40 --- src/lib/components/ui/data-table/index.ts | 3 - .../ui/data-table/render-helpers.ts | 111 -------- .../components/ui/dialog/dialog-close.svelte | 11 - .../ui/dialog/dialog-content.svelte | 48 ---- .../ui/dialog/dialog-description.svelte | 17 -- .../components/ui/dialog/dialog-footer.svelte | 32 --- .../components/ui/dialog/dialog-header.svelte | 20 -- .../ui/dialog/dialog-overlay.svelte | 17 -- .../components/ui/dialog/dialog-portal.svelte | 7 - .../components/ui/dialog/dialog-title.svelte | 17 -- .../ui/dialog/dialog-trigger.svelte | 11 - src/lib/components/ui/dialog/dialog.svelte | 7 - src/lib/components/ui/dialog/index.ts | 34 --- .../components/ui/drawer/drawer-close.svelte | 7 - .../ui/drawer/drawer-content.svelte | 33 --- .../ui/drawer/drawer-description.svelte | 17 -- .../components/ui/drawer/drawer-footer.svelte | 20 -- .../components/ui/drawer/drawer-header.svelte | 20 -- .../components/ui/drawer/drawer-nested.svelte | 12 - .../ui/drawer/drawer-overlay.svelte | 17 -- .../components/ui/drawer/drawer-portal.svelte | 7 - .../components/ui/drawer/drawer-title.svelte | 17 -- .../ui/drawer/drawer-trigger.svelte | 7 - src/lib/components/ui/drawer/drawer.svelte | 12 - src/lib/components/ui/drawer/index.ts | 38 --- .../dropdown-menu-checkbox-group.svelte | 16 -- .../dropdown-menu-checkbox-item.svelte | 44 --- .../dropdown-menu-content.svelte | 31 --- .../dropdown-menu-group-heading.svelte | 22 -- .../dropdown-menu/dropdown-menu-group.svelte | 7 - .../dropdown-menu/dropdown-menu-item.svelte | 27 -- .../dropdown-menu/dropdown-menu-label.svelte | 24 -- .../dropdown-menu/dropdown-menu-portal.svelte | 7 - .../dropdown-menu-radio-group.svelte | 16 -- .../dropdown-menu-radio-item.svelte | 34 --- .../dropdown-menu-separator.svelte | 17 -- .../dropdown-menu-shortcut.svelte | 20 -- .../dropdown-menu-sub-content.svelte | 17 -- .../dropdown-menu-sub-trigger.svelte | 29 -- .../ui/dropdown-menu/dropdown-menu-sub.svelte | 7 - .../dropdown-menu-trigger.svelte | 7 - .../ui/dropdown-menu/dropdown-menu.svelte | 7 - src/lib/components/ui/dropdown-menu/index.ts | 54 ---- .../components/ui/empty/empty-content.svelte | 23 -- .../ui/empty/empty-description.svelte | 23 -- .../components/ui/empty/empty-header.svelte | 20 -- .../components/ui/empty/empty-media.svelte | 41 --- .../components/ui/empty/empty-title.svelte | 20 -- src/lib/components/ui/empty/empty.svelte | 23 -- src/lib/components/ui/empty/index.ts | 22 -- .../components/ui/field/field-content.svelte | 20 -- .../ui/field/field-description.svelte | 25 -- .../components/ui/field/field-error.svelte | 58 ---- .../components/ui/field/field-group.svelte | 23 -- .../components/ui/field/field-label.svelte | 25 -- .../components/ui/field/field-legend.svelte | 24 -- .../ui/field/field-separator.svelte | 35 --- src/lib/components/ui/field/field-set.svelte | 20 -- .../components/ui/field/field-title.svelte | 20 -- src/lib/components/ui/field/field.svelte | 47 ---- src/lib/components/ui/field/index.ts | 33 --- src/lib/components/ui/form/form-button.svelte | 7 - .../ui/form/form-description.svelte | 17 -- .../ui/form/form-element-field.svelte | 24 -- .../ui/form/form-field-errors.svelte | 30 --- src/lib/components/ui/form/form-field.svelte | 29 -- .../components/ui/form/form-fieldset.svelte | 15 -- src/lib/components/ui/form/form-label.svelte | 24 -- src/lib/components/ui/form/form-legend.svelte | 16 -- src/lib/components/ui/form/index.ts | 33 --- src/lib/components/ui/input-group/index.ts | 22 -- .../ui/input-group/input-group-addon.svelte | 52 ---- .../ui/input-group/input-group-button.svelte | 49 ---- .../ui/input-group/input-group-input.svelte | 20 -- .../ui/input-group/input-group-text.svelte | 19 -- .../input-group/input-group-textarea.svelte | 20 -- .../ui/input-group/input-group.svelte | 24 -- src/lib/components/ui/input/index.ts | 7 - src/lib/components/ui/input/input.svelte | 48 ---- src/lib/components/ui/label/index.ts | 7 - src/lib/components/ui/label/label.svelte | 20 -- src/lib/components/ui/menubar/index.ts | 55 ---- .../ui/menubar/menubar-checkbox-item.svelte | 46 ---- .../ui/menubar/menubar-content.svelte | 35 --- .../ui/menubar/menubar-group-heading.svelte | 22 -- .../ui/menubar/menubar-group.svelte | 12 - .../components/ui/menubar/menubar-item.svelte | 24 -- .../ui/menubar/menubar-label.svelte | 25 -- .../components/ui/menubar/menubar-menu.svelte | 7 - .../ui/menubar/menubar-portal.svelte | 7 - .../ui/menubar/menubar-radio-group.svelte | 11 - .../ui/menubar/menubar-radio-item.svelte | 37 --- .../ui/menubar/menubar-separator.svelte | 17 -- .../ui/menubar/menubar-shortcut.svelte | 20 -- .../ui/menubar/menubar-sub-content.svelte | 17 -- .../ui/menubar/menubar-sub-trigger.svelte | 29 -- .../components/ui/menubar/menubar-sub.svelte | 7 - .../ui/menubar/menubar-trigger.svelte | 17 -- src/lib/components/ui/menubar/menubar.svelte | 17 -- .../multi-select-combobox.svelte | 98 ------- src/lib/components/ui/pagination/index.ts | 31 --- .../ui/pagination/pagination-content.svelte | 20 -- .../ui/pagination/pagination-ellipsis.svelte | 22 -- .../ui/pagination/pagination-item.svelte | 14 - .../ui/pagination/pagination-link.svelte | 42 --- .../pagination/pagination-next-button.svelte | 31 --- .../ui/pagination/pagination-next.svelte | 26 -- .../pagination/pagination-prev-button.svelte | 31 --- .../ui/pagination/pagination-previous.svelte | 26 -- .../ui/pagination/pagination.svelte | 28 -- src/lib/components/ui/popover/index.ts | 28 -- .../ui/popover/popover-close.svelte | 7 - .../ui/popover/popover-content.svelte | 31 --- .../ui/popover/popover-description.svelte | 20 -- .../ui/popover/popover-header.svelte | 20 -- .../ui/popover/popover-portal.svelte | 7 - .../ui/popover/popover-title.svelte | 20 -- .../ui/popover/popover-trigger.svelte | 17 -- src/lib/components/ui/popover/popover.svelte | 7 - src/lib/components/ui/progress/index.ts | 7 - .../components/ui/progress/progress.svelte | 27 -- src/lib/components/ui/range-calendar/index.ts | 40 --- .../range-calendar-caption.svelte | 76 ------ .../range-calendar/range-calendar-cell.svelte | 19 -- .../range-calendar/range-calendar-day.svelte | 36 --- .../range-calendar-grid-body.svelte | 7 - .../range-calendar-grid-head.svelte | 7 - .../range-calendar-grid-row.svelte | 12 - .../range-calendar/range-calendar-grid.svelte | 16 -- .../range-calendar-head-cell.svelte | 19 -- .../range-calendar-header.svelte | 19 -- .../range-calendar-heading.svelte | 16 -- .../range-calendar-month-select.svelte | 44 --- .../range-calendar-month.svelte | 15 -- .../range-calendar-months.svelte | 19 -- .../range-calendar/range-calendar-nav.svelte | 19 -- .../range-calendar-next-button.svelte | 36 --- .../range-calendar-prev-button.svelte | 36 --- .../range-calendar-year-select.svelte | 43 --- .../ui/range-calendar/range-calendar.svelte | 112 -------- src/lib/components/ui/scroll-area/index.ts | 10 - .../scroll-area/scroll-area-scrollbar.svelte | 30 --- .../ui/scroll-area/scroll-area.svelte | 43 --- src/lib/components/ui/select/index.ts | 37 --- .../ui/select/select-content.svelte | 45 ---- .../ui/select/select-group-heading.svelte | 21 -- .../components/ui/select/select-group.svelte | 17 -- .../components/ui/select/select-item.svelte | 40 --- .../components/ui/select/select-label.svelte | 20 -- .../components/ui/select/select-portal.svelte | 7 - .../select/select-scroll-down-button.svelte | 20 -- .../ui/select/select-scroll-up-button.svelte | 20 -- .../ui/select/select-separator.svelte | 18 -- .../ui/select/select-trigger.svelte | 29 -- src/lib/components/ui/select/select.svelte | 11 - src/lib/components/ui/separator/index.ts | 7 - .../components/ui/separator/separator.svelte | 23 -- src/lib/components/ui/sheet/index.ts | 34 --- .../components/ui/sheet/sheet-close.svelte | 7 - .../components/ui/sheet/sheet-content.svelte | 55 ---- .../ui/sheet/sheet-description.svelte | 17 -- .../components/ui/sheet/sheet-footer.svelte | 20 -- .../components/ui/sheet/sheet-header.svelte | 20 -- .../components/ui/sheet/sheet-overlay.svelte | 17 -- .../components/ui/sheet/sheet-portal.svelte | 7 - .../components/ui/sheet/sheet-title.svelte | 17 -- .../components/ui/sheet/sheet-trigger.svelte | 7 - src/lib/components/ui/sheet/sheet.svelte | 7 - src/lib/components/ui/sidebar/constants.ts | 6 - .../components/ui/sidebar/context.svelte.ts | 81 ------ src/lib/components/ui/sidebar/index.ts | 75 ------ .../ui/sidebar/sidebar-content.svelte | 24 -- .../ui/sidebar/sidebar-footer.svelte | 21 -- .../ui/sidebar/sidebar-group-action.svelte | 33 --- .../ui/sidebar/sidebar-group-content.svelte | 21 -- .../ui/sidebar/sidebar-group-label.svelte | 33 --- .../ui/sidebar/sidebar-group.svelte | 21 -- .../ui/sidebar/sidebar-header.svelte | 21 -- .../ui/sidebar/sidebar-input.svelte | 21 -- .../ui/sidebar/sidebar-inset.svelte | 20 -- .../ui/sidebar/sidebar-menu-action.svelte | 37 --- .../ui/sidebar/sidebar-menu-badge.svelte | 24 -- .../ui/sidebar/sidebar-menu-button.svelte | 102 ------- .../ui/sidebar/sidebar-menu-item.svelte | 21 -- .../ui/sidebar/sidebar-menu-skeleton.svelte | 36 --- .../ui/sidebar/sidebar-menu-sub-button.svelte | 39 --- .../ui/sidebar/sidebar-menu-sub-item.svelte | 21 -- .../ui/sidebar/sidebar-menu-sub.svelte | 21 -- .../components/ui/sidebar/sidebar-menu.svelte | 21 -- .../ui/sidebar/sidebar-provider.svelte | 53 ---- .../components/ui/sidebar/sidebar-rail.svelte | 36 --- .../ui/sidebar/sidebar-separator.svelte | 19 -- .../ui/sidebar/sidebar-trigger.svelte | 36 --- src/lib/components/ui/sidebar/sidebar.svelte | 108 -------- src/lib/components/ui/skeleton/index.ts | 7 - .../components/ui/skeleton/skeleton.svelte | 17 -- src/lib/components/ui/slider/index.ts | 7 - src/lib/components/ui/slider/slider.svelte | 52 ---- src/lib/components/ui/sonner/index.ts | 1 - src/lib/components/ui/sonner/sonner.svelte | 34 --- src/lib/components/ui/spinner/index.ts | 1 - src/lib/components/ui/spinner/spinner.svelte | 18 -- src/lib/components/ui/switch/index.ts | 7 - src/lib/components/ui/switch/switch.svelte | 31 --- src/lib/components/ui/table/index.ts | 28 -- src/lib/components/ui/table/table-body.svelte | 15 -- .../components/ui/table/table-caption.svelte | 20 -- src/lib/components/ui/table/table-cell.svelte | 15 -- .../components/ui/table/table-footer.svelte | 20 -- src/lib/components/ui/table/table-head.svelte | 15 -- .../components/ui/table/table-header.svelte | 20 -- src/lib/components/ui/table/table-row.svelte | 15 -- src/lib/components/ui/table/table.svelte | 17 -- src/lib/components/ui/tabs/index.ts | 18 -- .../components/ui/tabs/tabs-content.svelte | 17 -- src/lib/components/ui/tabs/tabs-list.svelte | 40 --- .../components/ui/tabs/tabs-trigger.svelte | 23 -- src/lib/components/ui/tabs/tabs.svelte | 19 -- src/lib/components/ui/textarea/index.ts | 7 - .../components/ui/textarea/textarea.svelte | 23 -- src/lib/components/ui/toggle-group/index.ts | 10 - .../ui/toggle-group/toggle-group-item.svelte | 35 --- .../ui/toggle-group/toggle-group.svelte | 76 ------ src/lib/components/ui/toggle/index.ts | 13 - src/lib/components/ui/toggle/toggle.svelte | 51 ---- src/lib/components/ui/tooltip/index.ts | 19 -- .../ui/tooltip/tooltip-content.svelte | 52 ---- .../ui/tooltip/tooltip-portal.svelte | 7 - .../ui/tooltip/tooltip-provider.svelte | 7 - .../ui/tooltip/tooltip-trigger.svelte | 7 - src/lib/components/ui/tooltip/tooltip.svelte | 7 - .../components/utils/MultiPauseToggle.svelte | 4 +- src/lib/components/utils/PauseToggle.svelte | 4 +- src/lib/errorhandling/ProblemDetails.ts | 3 +- .../errorhandling/ValidationProblemDetails.ts | 4 +- src/lib/hooks/is-mobile.svelte.ts | 9 - .../inputvalidation/emailValidator.test.ts | 200 -------------- src/lib/inputvalidation/emailValidator.ts | 46 ---- .../inputvalidation/passwordValidator.test.ts | 182 ------------- src/lib/inputvalidation/passwordValidator.ts | 92 ------- src/lib/inputvalidation/usernameValidator.ts | 4 +- src/lib/signalr/handlers/DeviceUpdate.ts | 2 +- src/lib/signalr/handlers/OtaInstallFailed.ts | 2 +- .../signalr/handlers/OtaInstallProgress.ts | 2 +- src/lib/signalr/handlers/OtaInstallStarted.ts | 2 +- .../signalr/handlers/OtaInstallSucceeded.ts | 2 +- src/lib/signalr/handlers/OtaRollback.ts | 2 +- src/lib/signalr/models/ControlLog.ts | 3 +- src/lib/signalr/models/ControlLogSender.ts | 3 +- src/lib/signalr/models/ControlType.ts | 2 +- src/lib/signalr/models/DeviceOnlineState.ts | 3 +- src/lib/signalr/models/HubUpdateType.ts | 2 +- .../signalr/models/OtaUpdateProgressTask.ts | 2 +- src/lib/state/auth-state.svelte.ts | 2 +- src/lib/state/color-scheme-state.svelte.ts | 2 +- src/lib/telemetry/common.ts | 2 +- src/lib/telemetry/tracer.ts | 2 +- src/lib/tour/onboarding-state.ts | 2 +- src/lib/typeguards/basicGuards.ts | 18 -- src/lib/typeguards/index.ts | 2 - src/lib/typeguards/propGuards.ts | 47 ---- src/lib/typeguards/twitterHandleGuard.ts | 5 - src/lib/types/AnyComponent.ts | 7 - src/lib/types/ChildrenFunc.ts | 3 - src/lib/types/Tailwind.ts | 11 - src/lib/types/ValidationResult.ts | 13 - src/lib/utils/clipboard.svelte.ts | 71 ----- src/lib/utils/convert.test.ts | Bin 7115 -> 0 bytes src/lib/utils/convert.ts | 22 -- src/lib/utils/crypto.test.ts | 87 ------ src/lib/utils/crypto.ts | 17 -- src/lib/utils/debounce.test.ts | 176 ------------ src/lib/utils/debounce.ts | 53 ---- src/lib/utils/encoding.test.ts | 82 ------ src/lib/utils/encoding.ts | 12 - src/lib/utils/entropy.test.ts | 56 ---- src/lib/utils/entropy.ts | 7 - src/lib/utils/index.ts | 9 - src/lib/utils/math.test.ts | 122 --------- src/lib/utils/math.ts | 19 -- src/lib/utils/md5.test.ts | 62 ----- src/lib/utils/md5.ts | 155 ----------- src/lib/utils/parse.test.ts | 61 ----- src/lib/utils/parse.ts | 31 --- src/lib/utils/rand.test.ts | 46 ---- src/lib/utils/rand.ts | 14 - src/lib/utils/shadcn.ts | 11 - src/lib/utils/temporal.test.ts | 138 ---------- src/lib/utils/temporal.ts | 25 -- src/lib/utils/time.test.ts | 154 ----------- src/lib/utils/time.ts | 41 --- src/routes/(app)/+layout.svelte | 4 +- src/routes/(app)/admin/+layout.svelte | 2 +- .../(app)/admin/blacklists/+page.svelte | 18 +- src/routes/(app)/admin/config/+page.svelte | 6 +- .../admin/config/data-table-actions.svelte | 4 +- .../(app)/admin/config/dialog-item-add.svelte | 10 +- .../admin/config/dialog-item-delete.svelte | 2 +- .../admin/config/dialog-item-edit.svelte | 6 +- .../(app)/admin/online-hubs/+page.svelte | 6 +- .../online-hubs/data-table-actions.svelte | 6 +- src/routes/(app)/admin/users/+page.svelte | 8 +- .../(app)/admin/users/[userId]/+page.svelte | 6 +- .../admin/users/data-table-actions.svelte | 6 +- .../admin/users/dialog-user-delete.svelte | 2 +- .../(app)/admin/users/dialog-user-edit.svelte | 8 +- src/routes/(app)/admin/webhooks/+page.svelte | 6 +- .../admin/webhooks/data-table-actions.svelte | 6 +- .../admin/webhooks/dialog-webhook-add.svelte | 8 +- .../webhooks/dialog-webhook-delete.svelte | 2 +- src/routes/(app)/hangfire/+page.svelte | 2 +- src/routes/(app)/home/+page.svelte | 6 +- src/routes/(app)/hubs/+page.svelte | 18 +- .../hubs/[hubId=guid]/update/+page.svelte | 18 +- .../(app)/hubs/data-table-actions.svelte | 20 +- src/routes/(app)/profile/+page.svelte | 2 +- .../(app)/settings/account/+page.svelte | 6 +- .../(app)/settings/account/DangerZone.svelte | 4 +- .../account/dialog-email-change.svelte | 8 +- .../account/dialog-password-change.svelte | 8 +- .../account/dialog-username-change.svelte | 4 +- .../(app)/settings/api-tokens/+page.svelte | 6 +- .../api-tokens/data-table-actions.svelte | 16 +- .../api-tokens/dialog-token-edit.svelte | 10 +- .../settings/api-tokens/new/+page.svelte | 14 +- .../shocker-control-settings.svelte | 10 +- .../(app)/settings/connections/+page.svelte | 12 +- .../dialog-oauth-disconnect.svelte | 4 +- .../connections/provider-button.svelte | 2 +- .../(app)/settings/sessions/+page.svelte | 6 +- .../sessions/data-table-actions.svelte | 6 +- .../sessions/dialog-session-revoke.svelte | 2 +- src/routes/(app)/shares/public/+page.svelte | 14 +- .../public/[shareId=guid]/edit/+page.svelte | 10 +- .../[shareId=guid]/edit/SharedShocker.svelte | 10 +- .../edit/dialog-add-shocker.svelte | 6 +- .../shares/public/data-table-actions.svelte | 6 +- .../public/dialog-publicshare-create.svelte | 6 +- .../public/dialog-publicshare-delete.svelte | 2 +- src/routes/(app)/shares/user/+layout.svelte | 8 +- .../user/dialog-share-code-create.svelte | 6 +- .../user/dialog-share-code-created.svelte | 4 +- .../user/dialog-share-code-redeem.svelte | 12 +- .../(app)/shares/user/incoming/+page.svelte | 6 +- .../user/incoming/incoming-share-item.svelte | 12 +- .../shares/user/incoming/manage-share.svelte | 12 +- .../(app)/shares/user/invites/+page.svelte | 6 +- .../user/invites/incoming-invite-item.svelte | 14 +- .../user/invites/outgoing-invite-item.svelte | 16 +- .../(app)/shares/user/outgoing/+page.svelte | 6 +- .../shares/user/outgoing/edit-share.svelte | 12 +- .../user/outgoing/user-share-item.svelte | 8 +- .../[shockerId=guid]/edit/+page.svelte | 18 +- src/routes/(app)/shockers/logs/+page.svelte | 10 +- src/routes/(app)/shockers/own/+page.svelte | 14 +- src/routes/(app)/shockers/shared/+page.svelte | 14 +- src/routes/(auth)/+layout.svelte | 2 +- src/routes/(auth)/activate/+page.svelte | 4 +- .../(auth)/forgot-password/+page.svelte | 8 +- src/routes/(auth)/login/+page.svelte | 21 +- .../oauth/[provider]/create/+page.svelte | 8 +- src/routes/(auth)/oauth/error/+page.svelte | 4 +- .../[secret]/+page.svelte | 8 +- src/routes/(auth)/signup/+page.svelte | 20 +- src/routes/(auth)/verify-email/+page.svelte | 4 +- src/routes/(meta)/llms.txt/+server.ts | 2 +- src/routes/(meta)/robots.txt/+server.ts | 2 +- src/routes/(meta)/sitemap.xml/+server.ts | 2 +- src/routes/+error.svelte | 2 +- src/routes/+layout.server.ts | 4 +- src/routes/+layout.svelte | 12 +- src/routes/+page.svelte | 2 +- src/routes/Breadcrumb.svelte | 2 +- src/routes/Footer.svelte | 4 +- src/routes/Header.svelte | 30 ++- src/routes/Sidebar.svelte | 4 +- src/routes/WelcomeScreen.svelte | 8 +- src/routes/report/api-tokens/+page.svelte | 12 +- .../shares/public/[shareId=guid]/+page.svelte | 6 +- .../public/[shareId=guid]/ControlView.svelte | 8 +- src/routes/terminal/+page.svelte | 20 +- src/routes/terminal/DeviceConfigurator.svelte | 16 +- src/routes/terminal/EspSerialConnection.ts | 4 +- .../terminal/FirmwareBoardSelector.svelte | 8 +- src/routes/terminal/FirmwareFlasher.svelte | 4 +- src/routes/terminal/HelpDialog.svelte | 10 +- src/routes/terminal/ModePicker.svelte | 2 +- .../terminal/RiskAcknowledgementModal.svelte | 4 +- src/routes/terminal/SerialPortSelector.svelte | 4 +- src/routes/terminal/SerialTerminal.svelte | 2 +- svelte.config.js | 7 + 543 files changed, 555 insertions(+), 13017 deletions(-) delete mode 100644 components.json delete mode 100644 scripts/update-shadcn.js delete mode 100644 src/lib/api/pwnedPasswords.ts delete mode 100644 src/lib/components/Code.svelte delete mode 100644 src/lib/components/ConfirmDeleteDialog.svelte delete mode 100644 src/lib/components/Container.svelte delete mode 100644 src/lib/components/CopyInput.svelte delete mode 100644 src/lib/components/DotGrid.svelte delete mode 100644 src/lib/components/EmptyState.svelte delete mode 100644 src/lib/components/Keyboard.svelte delete mode 100644 src/lib/components/LightSwitch.svelte delete mode 100644 src/lib/components/PageHeader.svelte delete mode 100644 src/lib/components/TableActionMenu.svelte delete mode 100644 src/lib/components/datetime-picker/date-time-picker.svelte delete mode 100644 src/lib/components/datetime-picker/time-picker-input.svelte delete mode 100644 src/lib/components/datetime-picker/time-picker-utils.ts delete mode 100644 src/lib/components/datetime-picker/time-picker.svelte delete mode 100644 src/lib/components/dialog-manager/dialog-alert-content.svelte delete mode 100644 src/lib/components/dialog-manager/dialog-confirm-content.svelte delete mode 100644 src/lib/components/dialog-manager/dialog-custom-content.svelte delete mode 100644 src/lib/components/dialog-manager/dialog-manager.svelte delete mode 100644 src/lib/components/dialog-manager/dialog-store.svelte.ts delete mode 100644 src/lib/components/dialog-manager/types.ts delete mode 100644 src/lib/components/input/EmailInput.svelte delete mode 100644 src/lib/components/input/PasswordInput.svelte delete mode 100644 src/lib/components/input/TextInput.svelte delete mode 100644 src/lib/components/input/impl/PasswordStrengthMeter.svelte delete mode 100644 src/lib/components/metadata/BasicTags.svelte delete mode 100644 src/lib/components/metadata/OpenGraphTags.svelte delete mode 100644 src/lib/components/metadata/Twitter/TwitterAppTags.svelte delete mode 100644 src/lib/components/metadata/Twitter/TwitterPlayerTags.svelte delete mode 100644 src/lib/components/metadata/Twitter/TwitterSummaryTags.svelte delete mode 100644 src/lib/components/metadata/Twitter/index.ts delete mode 100644 src/lib/components/metadata/index.ts delete mode 100644 src/lib/components/svg/ChromeLogo.svelte delete mode 100644 src/lib/components/svg/CloudflareLogo.svelte delete mode 100644 src/lib/components/svg/DiscordLogo.svelte delete mode 100644 src/lib/components/svg/EdgeLogo.svelte delete mode 100644 src/lib/components/svg/GithubIcon.svelte delete mode 100644 src/lib/components/svg/GoogleLogo.svelte delete mode 100644 src/lib/components/svg/OperaLogo.svelte delete mode 100644 src/lib/components/svg/XLogo.svelte delete mode 100644 src/lib/components/ui/README.md delete mode 100644 src/lib/components/ui/accordion/accordion-content.svelte delete mode 100644 src/lib/components/ui/accordion/accordion-item.svelte delete mode 100644 src/lib/components/ui/accordion/accordion-trigger.svelte delete mode 100644 src/lib/components/ui/accordion/accordion.svelte delete mode 100644 src/lib/components/ui/accordion/index.ts delete mode 100644 src/lib/components/ui/avatar/avatar-badge.svelte delete mode 100644 src/lib/components/ui/avatar/avatar-fallback.svelte delete mode 100644 src/lib/components/ui/avatar/avatar-group-count.svelte delete mode 100644 src/lib/components/ui/avatar/avatar-group.svelte delete mode 100644 src/lib/components/ui/avatar/avatar-image.svelte delete mode 100644 src/lib/components/ui/avatar/avatar.svelte delete mode 100644 src/lib/components/ui/avatar/index.ts delete mode 100644 src/lib/components/ui/badge/badge.svelte delete mode 100644 src/lib/components/ui/badge/index.ts delete mode 100644 src/lib/components/ui/breadcrumb/breadcrumb-ellipsis.svelte delete mode 100644 src/lib/components/ui/breadcrumb/breadcrumb-item.svelte delete mode 100644 src/lib/components/ui/breadcrumb/breadcrumb-link.svelte delete mode 100644 src/lib/components/ui/breadcrumb/breadcrumb-list.svelte delete mode 100644 src/lib/components/ui/breadcrumb/breadcrumb-page.svelte delete mode 100644 src/lib/components/ui/breadcrumb/breadcrumb-separator.svelte delete mode 100644 src/lib/components/ui/breadcrumb/breadcrumb.svelte delete mode 100644 src/lib/components/ui/breadcrumb/index.ts delete mode 100644 src/lib/components/ui/button/button.svelte delete mode 100644 src/lib/components/ui/button/index.ts delete mode 100644 src/lib/components/ui/calendar/calendar-caption.svelte delete mode 100644 src/lib/components/ui/calendar/calendar-cell.svelte delete mode 100644 src/lib/components/ui/calendar/calendar-day.svelte delete mode 100644 src/lib/components/ui/calendar/calendar-grid-body.svelte delete mode 100644 src/lib/components/ui/calendar/calendar-grid-head.svelte delete mode 100644 src/lib/components/ui/calendar/calendar-grid-row.svelte delete mode 100644 src/lib/components/ui/calendar/calendar-grid.svelte delete mode 100644 src/lib/components/ui/calendar/calendar-head-cell.svelte delete mode 100644 src/lib/components/ui/calendar/calendar-header.svelte delete mode 100644 src/lib/components/ui/calendar/calendar-heading.svelte delete mode 100644 src/lib/components/ui/calendar/calendar-month-select.svelte delete mode 100644 src/lib/components/ui/calendar/calendar-month.svelte delete mode 100644 src/lib/components/ui/calendar/calendar-months.svelte delete mode 100644 src/lib/components/ui/calendar/calendar-nav.svelte delete mode 100644 src/lib/components/ui/calendar/calendar-next-button.svelte delete mode 100644 src/lib/components/ui/calendar/calendar-prev-button.svelte delete mode 100644 src/lib/components/ui/calendar/calendar-year-select.svelte delete mode 100644 src/lib/components/ui/calendar/calendar.svelte delete mode 100644 src/lib/components/ui/calendar/index.ts delete mode 100644 src/lib/components/ui/card/card-action.svelte delete mode 100644 src/lib/components/ui/card/card-content.svelte delete mode 100644 src/lib/components/ui/card/card-description.svelte delete mode 100644 src/lib/components/ui/card/card-footer.svelte delete mode 100644 src/lib/components/ui/card/card-header.svelte delete mode 100644 src/lib/components/ui/card/card-title.svelte delete mode 100644 src/lib/components/ui/card/card.svelte delete mode 100644 src/lib/components/ui/card/index.ts delete mode 100644 src/lib/components/ui/checkbox/checkbox.svelte delete mode 100644 src/lib/components/ui/checkbox/index.ts delete mode 100644 src/lib/components/ui/collapsible/collapsible-content.svelte delete mode 100644 src/lib/components/ui/collapsible/collapsible-trigger.svelte delete mode 100644 src/lib/components/ui/collapsible/collapsible.svelte delete mode 100644 src/lib/components/ui/collapsible/index.ts delete mode 100644 src/lib/components/ui/command/command-dialog.svelte delete mode 100644 src/lib/components/ui/command/command-empty.svelte delete mode 100644 src/lib/components/ui/command/command-group.svelte delete mode 100644 src/lib/components/ui/command/command-input.svelte delete mode 100644 src/lib/components/ui/command/command-item.svelte delete mode 100644 src/lib/components/ui/command/command-link-item.svelte delete mode 100644 src/lib/components/ui/command/command-list.svelte delete mode 100644 src/lib/components/ui/command/command-loading.svelte delete mode 100644 src/lib/components/ui/command/command-separator.svelte delete mode 100644 src/lib/components/ui/command/command-shortcut.svelte delete mode 100644 src/lib/components/ui/command/command.svelte delete mode 100644 src/lib/components/ui/command/index.ts delete mode 100644 src/lib/components/ui/data-table/data-table.svelte.ts delete mode 100644 src/lib/components/ui/data-table/flex-render.svelte delete mode 100644 src/lib/components/ui/data-table/index.ts delete mode 100644 src/lib/components/ui/data-table/render-helpers.ts delete mode 100644 src/lib/components/ui/dialog/dialog-close.svelte delete mode 100644 src/lib/components/ui/dialog/dialog-content.svelte delete mode 100644 src/lib/components/ui/dialog/dialog-description.svelte delete mode 100644 src/lib/components/ui/dialog/dialog-footer.svelte delete mode 100644 src/lib/components/ui/dialog/dialog-header.svelte delete mode 100644 src/lib/components/ui/dialog/dialog-overlay.svelte delete mode 100644 src/lib/components/ui/dialog/dialog-portal.svelte delete mode 100644 src/lib/components/ui/dialog/dialog-title.svelte delete mode 100644 src/lib/components/ui/dialog/dialog-trigger.svelte delete mode 100644 src/lib/components/ui/dialog/dialog.svelte delete mode 100644 src/lib/components/ui/dialog/index.ts delete mode 100644 src/lib/components/ui/drawer/drawer-close.svelte delete mode 100644 src/lib/components/ui/drawer/drawer-content.svelte delete mode 100644 src/lib/components/ui/drawer/drawer-description.svelte delete mode 100644 src/lib/components/ui/drawer/drawer-footer.svelte delete mode 100644 src/lib/components/ui/drawer/drawer-header.svelte delete mode 100644 src/lib/components/ui/drawer/drawer-nested.svelte delete mode 100644 src/lib/components/ui/drawer/drawer-overlay.svelte delete mode 100644 src/lib/components/ui/drawer/drawer-portal.svelte delete mode 100644 src/lib/components/ui/drawer/drawer-title.svelte delete mode 100644 src/lib/components/ui/drawer/drawer-trigger.svelte delete mode 100644 src/lib/components/ui/drawer/drawer.svelte delete mode 100644 src/lib/components/ui/drawer/index.ts delete mode 100644 src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte delete mode 100644 src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte delete mode 100644 src/lib/components/ui/dropdown-menu/dropdown-menu-content.svelte delete mode 100644 src/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte delete mode 100644 src/lib/components/ui/dropdown-menu/dropdown-menu-group.svelte delete mode 100644 src/lib/components/ui/dropdown-menu/dropdown-menu-item.svelte delete mode 100644 src/lib/components/ui/dropdown-menu/dropdown-menu-label.svelte delete mode 100644 src/lib/components/ui/dropdown-menu/dropdown-menu-portal.svelte delete mode 100644 src/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte delete mode 100644 src/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte delete mode 100644 src/lib/components/ui/dropdown-menu/dropdown-menu-separator.svelte delete mode 100644 src/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte delete mode 100644 src/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte delete mode 100644 src/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte delete mode 100644 src/lib/components/ui/dropdown-menu/dropdown-menu-sub.svelte delete mode 100644 src/lib/components/ui/dropdown-menu/dropdown-menu-trigger.svelte delete mode 100644 src/lib/components/ui/dropdown-menu/dropdown-menu.svelte delete mode 100644 src/lib/components/ui/dropdown-menu/index.ts delete mode 100644 src/lib/components/ui/empty/empty-content.svelte delete mode 100644 src/lib/components/ui/empty/empty-description.svelte delete mode 100644 src/lib/components/ui/empty/empty-header.svelte delete mode 100644 src/lib/components/ui/empty/empty-media.svelte delete mode 100644 src/lib/components/ui/empty/empty-title.svelte delete mode 100644 src/lib/components/ui/empty/empty.svelte delete mode 100644 src/lib/components/ui/empty/index.ts delete mode 100644 src/lib/components/ui/field/field-content.svelte delete mode 100644 src/lib/components/ui/field/field-description.svelte delete mode 100644 src/lib/components/ui/field/field-error.svelte delete mode 100644 src/lib/components/ui/field/field-group.svelte delete mode 100644 src/lib/components/ui/field/field-label.svelte delete mode 100644 src/lib/components/ui/field/field-legend.svelte delete mode 100644 src/lib/components/ui/field/field-separator.svelte delete mode 100644 src/lib/components/ui/field/field-set.svelte delete mode 100644 src/lib/components/ui/field/field-title.svelte delete mode 100644 src/lib/components/ui/field/field.svelte delete mode 100644 src/lib/components/ui/field/index.ts delete mode 100644 src/lib/components/ui/form/form-button.svelte delete mode 100644 src/lib/components/ui/form/form-description.svelte delete mode 100644 src/lib/components/ui/form/form-element-field.svelte delete mode 100644 src/lib/components/ui/form/form-field-errors.svelte delete mode 100644 src/lib/components/ui/form/form-field.svelte delete mode 100644 src/lib/components/ui/form/form-fieldset.svelte delete mode 100644 src/lib/components/ui/form/form-label.svelte delete mode 100644 src/lib/components/ui/form/form-legend.svelte delete mode 100644 src/lib/components/ui/form/index.ts delete mode 100644 src/lib/components/ui/input-group/index.ts delete mode 100644 src/lib/components/ui/input-group/input-group-addon.svelte delete mode 100644 src/lib/components/ui/input-group/input-group-button.svelte delete mode 100644 src/lib/components/ui/input-group/input-group-input.svelte delete mode 100644 src/lib/components/ui/input-group/input-group-text.svelte delete mode 100644 src/lib/components/ui/input-group/input-group-textarea.svelte delete mode 100644 src/lib/components/ui/input-group/input-group.svelte delete mode 100644 src/lib/components/ui/input/index.ts delete mode 100644 src/lib/components/ui/input/input.svelte delete mode 100644 src/lib/components/ui/label/index.ts delete mode 100644 src/lib/components/ui/label/label.svelte delete mode 100644 src/lib/components/ui/menubar/index.ts delete mode 100644 src/lib/components/ui/menubar/menubar-checkbox-item.svelte delete mode 100644 src/lib/components/ui/menubar/menubar-content.svelte delete mode 100644 src/lib/components/ui/menubar/menubar-group-heading.svelte delete mode 100644 src/lib/components/ui/menubar/menubar-group.svelte delete mode 100644 src/lib/components/ui/menubar/menubar-item.svelte delete mode 100644 src/lib/components/ui/menubar/menubar-label.svelte delete mode 100644 src/lib/components/ui/menubar/menubar-menu.svelte delete mode 100644 src/lib/components/ui/menubar/menubar-portal.svelte delete mode 100644 src/lib/components/ui/menubar/menubar-radio-group.svelte delete mode 100644 src/lib/components/ui/menubar/menubar-radio-item.svelte delete mode 100644 src/lib/components/ui/menubar/menubar-separator.svelte delete mode 100644 src/lib/components/ui/menubar/menubar-shortcut.svelte delete mode 100644 src/lib/components/ui/menubar/menubar-sub-content.svelte delete mode 100644 src/lib/components/ui/menubar/menubar-sub-trigger.svelte delete mode 100644 src/lib/components/ui/menubar/menubar-sub.svelte delete mode 100644 src/lib/components/ui/menubar/menubar-trigger.svelte delete mode 100644 src/lib/components/ui/menubar/menubar.svelte delete mode 100644 src/lib/components/ui/multi-select-combobox/multi-select-combobox.svelte delete mode 100644 src/lib/components/ui/pagination/index.ts delete mode 100644 src/lib/components/ui/pagination/pagination-content.svelte delete mode 100644 src/lib/components/ui/pagination/pagination-ellipsis.svelte delete mode 100644 src/lib/components/ui/pagination/pagination-item.svelte delete mode 100644 src/lib/components/ui/pagination/pagination-link.svelte delete mode 100644 src/lib/components/ui/pagination/pagination-next-button.svelte delete mode 100644 src/lib/components/ui/pagination/pagination-next.svelte delete mode 100644 src/lib/components/ui/pagination/pagination-prev-button.svelte delete mode 100644 src/lib/components/ui/pagination/pagination-previous.svelte delete mode 100644 src/lib/components/ui/pagination/pagination.svelte delete mode 100644 src/lib/components/ui/popover/index.ts delete mode 100644 src/lib/components/ui/popover/popover-close.svelte delete mode 100644 src/lib/components/ui/popover/popover-content.svelte delete mode 100644 src/lib/components/ui/popover/popover-description.svelte delete mode 100644 src/lib/components/ui/popover/popover-header.svelte delete mode 100644 src/lib/components/ui/popover/popover-portal.svelte delete mode 100644 src/lib/components/ui/popover/popover-title.svelte delete mode 100644 src/lib/components/ui/popover/popover-trigger.svelte delete mode 100644 src/lib/components/ui/popover/popover.svelte delete mode 100644 src/lib/components/ui/progress/index.ts delete mode 100644 src/lib/components/ui/progress/progress.svelte delete mode 100644 src/lib/components/ui/range-calendar/index.ts delete mode 100644 src/lib/components/ui/range-calendar/range-calendar-caption.svelte delete mode 100644 src/lib/components/ui/range-calendar/range-calendar-cell.svelte delete mode 100644 src/lib/components/ui/range-calendar/range-calendar-day.svelte delete mode 100644 src/lib/components/ui/range-calendar/range-calendar-grid-body.svelte delete mode 100644 src/lib/components/ui/range-calendar/range-calendar-grid-head.svelte delete mode 100644 src/lib/components/ui/range-calendar/range-calendar-grid-row.svelte delete mode 100644 src/lib/components/ui/range-calendar/range-calendar-grid.svelte delete mode 100644 src/lib/components/ui/range-calendar/range-calendar-head-cell.svelte delete mode 100644 src/lib/components/ui/range-calendar/range-calendar-header.svelte delete mode 100644 src/lib/components/ui/range-calendar/range-calendar-heading.svelte delete mode 100644 src/lib/components/ui/range-calendar/range-calendar-month-select.svelte delete mode 100644 src/lib/components/ui/range-calendar/range-calendar-month.svelte delete mode 100644 src/lib/components/ui/range-calendar/range-calendar-months.svelte delete mode 100644 src/lib/components/ui/range-calendar/range-calendar-nav.svelte delete mode 100644 src/lib/components/ui/range-calendar/range-calendar-next-button.svelte delete mode 100644 src/lib/components/ui/range-calendar/range-calendar-prev-button.svelte delete mode 100644 src/lib/components/ui/range-calendar/range-calendar-year-select.svelte delete mode 100644 src/lib/components/ui/range-calendar/range-calendar.svelte delete mode 100644 src/lib/components/ui/scroll-area/index.ts delete mode 100644 src/lib/components/ui/scroll-area/scroll-area-scrollbar.svelte delete mode 100644 src/lib/components/ui/scroll-area/scroll-area.svelte delete mode 100644 src/lib/components/ui/select/index.ts delete mode 100644 src/lib/components/ui/select/select-content.svelte delete mode 100644 src/lib/components/ui/select/select-group-heading.svelte delete mode 100644 src/lib/components/ui/select/select-group.svelte delete mode 100644 src/lib/components/ui/select/select-item.svelte delete mode 100644 src/lib/components/ui/select/select-label.svelte delete mode 100644 src/lib/components/ui/select/select-portal.svelte delete mode 100644 src/lib/components/ui/select/select-scroll-down-button.svelte delete mode 100644 src/lib/components/ui/select/select-scroll-up-button.svelte delete mode 100644 src/lib/components/ui/select/select-separator.svelte delete mode 100644 src/lib/components/ui/select/select-trigger.svelte delete mode 100644 src/lib/components/ui/select/select.svelte delete mode 100644 src/lib/components/ui/separator/index.ts delete mode 100644 src/lib/components/ui/separator/separator.svelte delete mode 100644 src/lib/components/ui/sheet/index.ts delete mode 100644 src/lib/components/ui/sheet/sheet-close.svelte delete mode 100644 src/lib/components/ui/sheet/sheet-content.svelte delete mode 100644 src/lib/components/ui/sheet/sheet-description.svelte delete mode 100644 src/lib/components/ui/sheet/sheet-footer.svelte delete mode 100644 src/lib/components/ui/sheet/sheet-header.svelte delete mode 100644 src/lib/components/ui/sheet/sheet-overlay.svelte delete mode 100644 src/lib/components/ui/sheet/sheet-portal.svelte delete mode 100644 src/lib/components/ui/sheet/sheet-title.svelte delete mode 100644 src/lib/components/ui/sheet/sheet-trigger.svelte delete mode 100644 src/lib/components/ui/sheet/sheet.svelte delete mode 100644 src/lib/components/ui/sidebar/constants.ts delete mode 100644 src/lib/components/ui/sidebar/context.svelte.ts delete mode 100644 src/lib/components/ui/sidebar/index.ts delete mode 100644 src/lib/components/ui/sidebar/sidebar-content.svelte delete mode 100644 src/lib/components/ui/sidebar/sidebar-footer.svelte delete mode 100644 src/lib/components/ui/sidebar/sidebar-group-action.svelte delete mode 100644 src/lib/components/ui/sidebar/sidebar-group-content.svelte delete mode 100644 src/lib/components/ui/sidebar/sidebar-group-label.svelte delete mode 100644 src/lib/components/ui/sidebar/sidebar-group.svelte delete mode 100644 src/lib/components/ui/sidebar/sidebar-header.svelte delete mode 100644 src/lib/components/ui/sidebar/sidebar-input.svelte delete mode 100644 src/lib/components/ui/sidebar/sidebar-inset.svelte delete mode 100644 src/lib/components/ui/sidebar/sidebar-menu-action.svelte delete mode 100644 src/lib/components/ui/sidebar/sidebar-menu-badge.svelte delete mode 100644 src/lib/components/ui/sidebar/sidebar-menu-button.svelte delete mode 100644 src/lib/components/ui/sidebar/sidebar-menu-item.svelte delete mode 100644 src/lib/components/ui/sidebar/sidebar-menu-skeleton.svelte delete mode 100644 src/lib/components/ui/sidebar/sidebar-menu-sub-button.svelte delete mode 100644 src/lib/components/ui/sidebar/sidebar-menu-sub-item.svelte delete mode 100644 src/lib/components/ui/sidebar/sidebar-menu-sub.svelte delete mode 100644 src/lib/components/ui/sidebar/sidebar-menu.svelte delete mode 100644 src/lib/components/ui/sidebar/sidebar-provider.svelte delete mode 100644 src/lib/components/ui/sidebar/sidebar-rail.svelte delete mode 100644 src/lib/components/ui/sidebar/sidebar-separator.svelte delete mode 100644 src/lib/components/ui/sidebar/sidebar-trigger.svelte delete mode 100644 src/lib/components/ui/sidebar/sidebar.svelte delete mode 100644 src/lib/components/ui/skeleton/index.ts delete mode 100644 src/lib/components/ui/skeleton/skeleton.svelte delete mode 100644 src/lib/components/ui/slider/index.ts delete mode 100644 src/lib/components/ui/slider/slider.svelte delete mode 100644 src/lib/components/ui/sonner/index.ts delete mode 100644 src/lib/components/ui/sonner/sonner.svelte delete mode 100644 src/lib/components/ui/spinner/index.ts delete mode 100644 src/lib/components/ui/spinner/spinner.svelte delete mode 100644 src/lib/components/ui/switch/index.ts delete mode 100644 src/lib/components/ui/switch/switch.svelte delete mode 100644 src/lib/components/ui/table/index.ts delete mode 100644 src/lib/components/ui/table/table-body.svelte delete mode 100644 src/lib/components/ui/table/table-caption.svelte delete mode 100644 src/lib/components/ui/table/table-cell.svelte delete mode 100644 src/lib/components/ui/table/table-footer.svelte delete mode 100644 src/lib/components/ui/table/table-head.svelte delete mode 100644 src/lib/components/ui/table/table-header.svelte delete mode 100644 src/lib/components/ui/table/table-row.svelte delete mode 100644 src/lib/components/ui/table/table.svelte delete mode 100644 src/lib/components/ui/tabs/index.ts delete mode 100644 src/lib/components/ui/tabs/tabs-content.svelte delete mode 100644 src/lib/components/ui/tabs/tabs-list.svelte delete mode 100644 src/lib/components/ui/tabs/tabs-trigger.svelte delete mode 100644 src/lib/components/ui/tabs/tabs.svelte delete mode 100644 src/lib/components/ui/textarea/index.ts delete mode 100644 src/lib/components/ui/textarea/textarea.svelte delete mode 100644 src/lib/components/ui/toggle-group/index.ts delete mode 100644 src/lib/components/ui/toggle-group/toggle-group-item.svelte delete mode 100644 src/lib/components/ui/toggle-group/toggle-group.svelte delete mode 100644 src/lib/components/ui/toggle/index.ts delete mode 100644 src/lib/components/ui/toggle/toggle.svelte delete mode 100644 src/lib/components/ui/tooltip/index.ts delete mode 100644 src/lib/components/ui/tooltip/tooltip-content.svelte delete mode 100644 src/lib/components/ui/tooltip/tooltip-portal.svelte delete mode 100644 src/lib/components/ui/tooltip/tooltip-provider.svelte delete mode 100644 src/lib/components/ui/tooltip/tooltip-trigger.svelte delete mode 100644 src/lib/components/ui/tooltip/tooltip.svelte delete mode 100644 src/lib/hooks/is-mobile.svelte.ts delete mode 100644 src/lib/inputvalidation/emailValidator.test.ts delete mode 100644 src/lib/inputvalidation/emailValidator.ts delete mode 100644 src/lib/inputvalidation/passwordValidator.test.ts delete mode 100644 src/lib/inputvalidation/passwordValidator.ts delete mode 100644 src/lib/typeguards/basicGuards.ts delete mode 100644 src/lib/typeguards/index.ts delete mode 100644 src/lib/typeguards/propGuards.ts delete mode 100644 src/lib/typeguards/twitterHandleGuard.ts delete mode 100644 src/lib/types/AnyComponent.ts delete mode 100644 src/lib/types/ChildrenFunc.ts delete mode 100644 src/lib/types/Tailwind.ts delete mode 100644 src/lib/types/ValidationResult.ts delete mode 100644 src/lib/utils/clipboard.svelte.ts delete mode 100644 src/lib/utils/convert.test.ts delete mode 100644 src/lib/utils/convert.ts delete mode 100644 src/lib/utils/crypto.test.ts delete mode 100644 src/lib/utils/crypto.ts delete mode 100644 src/lib/utils/debounce.test.ts delete mode 100644 src/lib/utils/debounce.ts delete mode 100644 src/lib/utils/encoding.test.ts delete mode 100644 src/lib/utils/encoding.ts delete mode 100644 src/lib/utils/entropy.test.ts delete mode 100644 src/lib/utils/entropy.ts delete mode 100644 src/lib/utils/math.test.ts delete mode 100644 src/lib/utils/math.ts delete mode 100644 src/lib/utils/md5.test.ts delete mode 100644 src/lib/utils/md5.ts delete mode 100644 src/lib/utils/parse.test.ts delete mode 100644 src/lib/utils/parse.ts delete mode 100644 src/lib/utils/rand.test.ts delete mode 100644 src/lib/utils/rand.ts delete mode 100644 src/lib/utils/shadcn.ts delete mode 100644 src/lib/utils/temporal.test.ts delete mode 100644 src/lib/utils/temporal.ts delete mode 100644 src/lib/utils/time.test.ts delete mode 100644 src/lib/utils/time.ts diff --git a/components.json b/components.json deleted file mode 100644 index 1df05563..00000000 --- a/components.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "$schema": "https://shadcn-svelte.com/schema.json", - "tailwind": { - "css": "src/app.css", - "baseColor": "neutral" - }, - "aliases": { - "components": "$lib/components", - "utils": "$lib/utils/shadcn", - "ui": "$lib/components/ui", - "hooks": "$lib/hooks", - "lib": "$lib" - }, - "typescript": true, - "registry": "https://shadcn-svelte.com/registry" -} diff --git a/package.json b/package.json index 936045aa..15cc5c20 100644 --- a/package.json +++ b/package.json @@ -72,6 +72,7 @@ "vitest": "^4.1.9" }, "dependencies": { + "@openshock/svelte-core": "^0.1.0", "@opentelemetry/api-logs": "^0.219.0", "@opentelemetry/exporter-logs-otlp-http": "^0.219.0", "@opentelemetry/exporter-trace-otlp-http": "^0.219.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bef1e545..3da9d62f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -19,6 +19,9 @@ importers: .: dependencies: + '@openshock/svelte-core': + specifier: ^0.1.0 + version: 0.1.0(2cd3459784afbbe2cb9606225751a11d) '@opentelemetry/api-logs': specifier: ^0.219.0 version: 0.219.0 @@ -750,6 +753,36 @@ packages: '@emnapi/core': ^1.7.1 '@emnapi/runtime': ^1.7.1 + '@openshock/svelte-core@0.1.0': + resolution: {integrity: sha512-x2Un0wxlbSc5zfgcCBMd8OI6CtaqgyWI2yPB72Ze97ZyUZy1SmUzWROo68lWyMhGwZJZ3MgU9dYilPNZamMKKQ==} + peerDependencies: + '@internationalized/date': ^3.12.2 + '@lucide/svelte': ^1.21.0 + '@tanstack/table-core': ^8.21.3 + bits-ui: 2.18.1 + clsx: ^2.1.1 + formsnap: ^2.0.1 + svelte: ^5.56.1 + svelte-sonner: ^1.1.1 + sveltekit-superforms: ^2.30.1 + tailwind-merge: ^3.6.0 + tailwind-variants: ^3.2.2 + temporal-polyfill: ^1.0.1 + vaul-svelte: 1.0.0-next.7 + peerDependenciesMeta: + '@internationalized/date': + optional: true + '@tanstack/table-core': + optional: true + formsnap: + optional: true + sveltekit-superforms: + optional: true + temporal-polyfill: + optional: true + vaul-svelte: + optional: true + '@opentelemetry/api-logs@0.219.0': resolution: {integrity: sha512-FFx7YnaYJlIjqWW/AG/yAZ0L/NEY724PipXXXQLdtZPbLwBGbUMTGL1i/esI56TWfTUXxhLfpgrnWJCG8aUJyg==} engines: {node: '>=8.0.0'} @@ -3442,6 +3475,23 @@ snapshots: '@tybys/wasm-util': 0.10.2 optional: true + '@openshock/svelte-core@0.1.0(2cd3459784afbbe2cb9606225751a11d)': + dependencies: + '@lucide/svelte': 1.21.0(svelte@5.56.3(@typescript-eslint/types@8.61.1)) + bits-ui: 2.18.1(@internationalized/date@3.12.2)(@sveltejs/kit@2.66.0(@opentelemetry/api@1.9.1)(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.56.3(@typescript-eslint/types@8.61.1))(vite@8.0.16(@types/node@26.0.0)(esbuild@0.27.3)(jiti@2.7.0)))(svelte@5.56.3(@typescript-eslint/types@8.61.1))(typescript@6.0.3)(vite@8.0.16(@types/node@26.0.0)(esbuild@0.27.3)(jiti@2.7.0)))(svelte@5.56.3(@typescript-eslint/types@8.61.1)) + clsx: 2.1.1 + svelte: 5.56.3(@typescript-eslint/types@8.61.1) + svelte-sonner: 1.1.1(svelte@5.56.3(@typescript-eslint/types@8.61.1)) + tailwind-merge: 3.6.0 + tailwind-variants: 3.2.2(tailwind-merge@3.6.0)(tailwindcss@4.3.1) + optionalDependencies: + '@internationalized/date': 3.12.2 + '@tanstack/table-core': 8.21.3 + formsnap: 2.0.1(svelte@5.56.3(@typescript-eslint/types@8.61.1))(sveltekit-superforms@2.30.1(@sveltejs/kit@2.66.0(@opentelemetry/api@1.9.1)(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.56.3(@typescript-eslint/types@8.61.1))(vite@8.0.16(@types/node@26.0.0)(esbuild@0.27.3)(jiti@2.7.0)))(svelte@5.56.3(@typescript-eslint/types@8.61.1))(typescript@6.0.3)(vite@8.0.16(@types/node@26.0.0)(esbuild@0.27.3)(jiti@2.7.0)))(@types/json-schema@7.0.15)(svelte@5.56.3(@typescript-eslint/types@8.61.1))(typescript@6.0.3)) + sveltekit-superforms: 2.30.1(@sveltejs/kit@2.66.0(@opentelemetry/api@1.9.1)(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.56.3(@typescript-eslint/types@8.61.1))(vite@8.0.16(@types/node@26.0.0)(esbuild@0.27.3)(jiti@2.7.0)))(svelte@5.56.3(@typescript-eslint/types@8.61.1))(typescript@6.0.3)(vite@8.0.16(@types/node@26.0.0)(esbuild@0.27.3)(jiti@2.7.0)))(@types/json-schema@7.0.15)(svelte@5.56.3(@typescript-eslint/types@8.61.1))(typescript@6.0.3) + temporal-polyfill: 1.0.1 + vaul-svelte: 1.0.0-next.7(svelte@5.56.3(@typescript-eslint/types@8.61.1)) + '@opentelemetry/api-logs@0.219.0': dependencies: '@opentelemetry/api': 1.9.1 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 402e0b1c..3cfc8e9a 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -6,6 +6,7 @@ blockExoticSubdeps: true minimumReleaseAge: 4320 # 3 days minimumReleaseAgeExclude: + - '@openshock/*' - ws@8.20.1 onlyBuiltDependencies: diff --git a/scripts/update-shadcn.js b/scripts/update-shadcn.js deleted file mode 100644 index 120becd3..00000000 --- a/scripts/update-shadcn.js +++ /dev/null @@ -1,103 +0,0 @@ -import { execSync } from 'node:child_process'; -import fs from 'node:fs'; -import path from 'node:path'; - -const UI_DIR = 'src/lib/components/ui'; -const HOOKS_DIR = 'src/lib/hooks'; - -// Non-shadcn directories to keep -const EXCLUDE = ['multi-select-combobox']; - -// Unwanted dependencies that the CLI tends to add -const UNWANTED_DEPS = ['mode-watcher']; - -function run(command, options = {}) { - execSync(command, { stdio: 'inherit', shell: true, ...options }); -} - -// Collect shadcn component names -const components = fs - .readdirSync(UI_DIR, { withFileTypes: true }) - .filter((entry) => entry.isDirectory() && !EXCLUDE.includes(entry.name)) - .map((entry) => entry.name); - -if (components.length === 0) { - console.error('No shadcn components found to update.'); - process.exit(1); -} - -console.log(`Found ${components.length} shadcn components: ${components.join(' ')}`); - -// Delete all shadcn component directories -console.log('Deleting shadcn components...'); -for (const name of components) { - fs.rmSync(path.join(UI_DIR, name), { recursive: true, force: true }); -} -fs.rmSync(path.join(HOOKS_DIR, 'is-mobile'), { recursive: true, force: true }); - -// Re-add all components -console.log('Re-adding components via shadcn CLI...'); -run(`pnpm dlx shadcn-svelte@latest add --yes --overwrite ${components.join(' ')}`); - -// Remove unwanted dependencies -console.log('Cleaning up dependencies...'); -const packageJson = fs.readFileSync('package.json', 'utf-8'); -for (const dep of UNWANTED_DEPS) { - if (packageJson.includes(`"${dep}"`)) { - console.log(` Removing unwanted dependency: ${dep}`); - run(`pnpm remove ${dep}`); - } -} - -// Format to reduce diff noise -console.log('Formatting...'); -run('pnpm run format'); - -// Apply custom modifications -console.log('Applying custom modifications...'); - -function patch(filePath, replacements) { - let source = fs.readFileSync(filePath, 'utf-8'); - for (const [pattern, replacement] of replacements) { - source = source.replace(pattern, replacement); - } - fs.writeFileSync(filePath, source); -} - -// Sidebar: ease-in-out and duration-300 -patch(path.join(UI_DIR, 'sidebar/sidebar.svelte'), [ - [/duration-200 ease-linear/g, 'duration-300 ease-in-out'], -]); - -// Sidebar submenu: ml-* instead of mx-*, pl-* instead of px-* -patch(path.join(UI_DIR, 'sidebar/sidebar-menu-sub.svelte'), [ - [/mx-3\.5(.*)px-2\.5/g, 'ml-3.5$1pl-2.5'], -]); - -// Sonner: use color-scheme-state instead of mode-watcher -patch(path.join(UI_DIR, 'sonner/sonner.svelte'), [ - [ - 'import { mode } from "mode-watcher";', - "import { colorScheme } from '$lib/state/color-scheme-state.svelte';", - ], - ['theme={mode.current}', 'theme={colorScheme.value}'], -]); - -// Slider: add cursor-w-resize to thumb -patch(path.join(UI_DIR, 'slider/slider.svelte'), [ - [/select-none disabled:pointer/, 'cursor-w-resize select-none disabled:pointer'], -]); - -// Toggle group: suppress state_referenced_locally warnings -patch(path.join(UI_DIR, 'toggle-group/toggle-group.svelte'), [ - [/\tsetToggleGroupCtx/, '\t// svelte-ignore state_referenced_locally\n\tsetToggleGroupCtx'], -]); - -// Final format and check -console.log('Final format...'); -run('pnpm run format'); - -console.log('Running checks...'); -run('pnpm run check'); - -console.log('Done! Review the git diff before committing.'); diff --git a/src/app.css b/src/app.css index 92185e03..78be2016 100644 --- a/src/app.css +++ b/src/app.css @@ -1,255 +1,6 @@ @import 'tailwindcss'; @import 'tw-animate-css'; - -@custom-variant dark (&:is(.dark *)); - -:root { - --radius: 0.625rem; - --background: oklch(1 0 0); - --foreground: oklch(0.145 0 0); - --card: oklch(1 0 0); - --card-foreground: oklch(0.145 0 0); - --popover: oklch(1 0 0); - --popover-foreground: oklch(0.145 0 0); - --primary: oklch(0.205 0 0); - --primary-foreground: oklch(0.985 0 0); - --secondary: oklch(0.97 0 0); - --secondary-foreground: oklch(0.205 0 0); - --muted: oklch(0.97 0 0); - --muted-foreground: oklch(0.556 0 0); - --accent: oklch(0.97 0 0); - --accent-foreground: oklch(0.205 0 0); - --destructive: oklch(0.577 0.245 27.325); - --border: oklch(0.922 0 0); - --input: oklch(0.922 0 0); - --ring: oklch(0.708 0 0); - --chart-1: oklch(0.646 0.222 41.116); - --chart-2: oklch(0.6 0.118 184.704); - --chart-3: oklch(0.398 0.07 227.392); - --chart-4: oklch(0.828 0.189 84.429); - --chart-5: oklch(0.769 0.188 70.08); - --sidebar: oklch(0.985 0 0); - --sidebar-foreground: oklch(0.145 0 0); - --sidebar-primary: oklch(0.205 0 0); - --sidebar-primary-foreground: oklch(0.985 0 0); - --sidebar-accent: oklch(0.97 0 0); - --sidebar-accent-foreground: oklch(0.205 0 0); - --sidebar-border: oklch(0.922 0 0); - --sidebar-ring: oklch(0.708 0 0); -} - -.dark { - --background: oklch(0.145 0 0); - --foreground: oklch(0.985 0 0); - --card: oklch(0.205 0 0); - --card-foreground: oklch(0.985 0 0); - --popover: oklch(0.205 0 0); - --popover-foreground: oklch(0.985 0 0); - --primary: oklch(0.922 0 0); - --primary-foreground: oklch(0.205 0 0); - --secondary: oklch(0.269 0 0); - --secondary-foreground: oklch(0.985 0 0); - --muted: oklch(0.269 0 0); - --muted-foreground: oklch(0.708 0 0); - --accent: oklch(0.269 0 0); - --accent-foreground: oklch(0.985 0 0); - --destructive: oklch(0.704 0.191 22.216); - --border: oklch(1 0 0 / 10%); - --input: oklch(1 0 0 / 15%); - --ring: oklch(0.556 0 0); - --chart-1: oklch(0.488 0.243 264.376); - --chart-2: oklch(0.696 0.17 162.48); - --chart-3: oklch(0.769 0.188 70.08); - --chart-4: oklch(0.627 0.265 303.9); - --chart-5: oklch(0.645 0.246 16.439); - --sidebar: oklch(0.205 0 0); - --sidebar-foreground: oklch(0.985 0 0); - --sidebar-primary: oklch(0.488 0.243 264.376); - --sidebar-primary-foreground: oklch(0.985 0 0); - --sidebar-accent: oklch(0.269 0 0); - --sidebar-accent-foreground: oklch(0.985 0 0); - --sidebar-border: oklch(1 0 0 / 10%); - --sidebar-ring: oklch(0.556 0 0); -} - -@theme inline { - --radius-sm: calc(var(--radius) - 4px); - --radius-md: calc(var(--radius) - 2px); - --radius-lg: var(--radius); - --radius-xl: calc(var(--radius) + 4px); - --color-background: var(--background); - --color-foreground: var(--foreground); - --color-card: var(--card); - --color-card-foreground: var(--card-foreground); - --color-popover: var(--popover); - --color-popover-foreground: var(--popover-foreground); - --color-primary: var(--primary); - --color-primary-foreground: var(--primary-foreground); - --color-secondary: var(--secondary); - --color-secondary-foreground: var(--secondary-foreground); - --color-muted: var(--muted); - --color-muted-foreground: var(--muted-foreground); - --color-accent: var(--accent); - --color-accent-foreground: var(--accent-foreground); - --color-destructive: var(--destructive); - --color-border: var(--border); - --color-input: var(--input); - --color-ring: var(--ring); - --color-chart-1: var(--chart-1); - --color-chart-2: var(--chart-2); - --color-chart-3: var(--chart-3); - --color-chart-4: var(--chart-4); - --color-chart-5: var(--chart-5); - --color-sidebar: var(--sidebar); - --color-sidebar-foreground: var(--sidebar-foreground); - --color-sidebar-primary: var(--sidebar-primary); - --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); - --color-sidebar-accent: var(--sidebar-accent); - --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); - --color-sidebar-border: var(--sidebar-border); - --color-sidebar-ring: var(--sidebar-ring); - - --animate-accordion-up: accordion-up 0.2s ease-out; - --animate-accordion-down: accordion-down 0.2s ease-out; - --animate-caret-blink: caret-blink 1.25s ease-out infinite; -} - -@layer base { - * { - @apply border-border outline-ring/50; - } - body { - @apply bg-background text-foreground; - } - - .hide-spinners { - /* Hide spin buttons in Chrome, Safari, Edge */ - -webkit-appearance: none; - -moz-appearance: textfield; /* Hide spinners in Firefox */ - appearance: textfield; - } - - /* Target WebKit browsers (Chrome, Safari, Edge) */ - .hide-spinners::-webkit-outer-spin-button, - .hide-spinners::-webkit-inner-spin-button { - -webkit-appearance: none; - margin: 0; - } - - button:not([disabled]), - [role='button']:not([disabled]) { - cursor: pointer; - } -} - -.transition-in-place { - display: grid; -} - -.transition-in-place > * { - grid-area: 1/1/2/2; -} - -@keyframes accordion-down { - from { - height: 0; - } - - to { - height: var(--bits-accordion-content-height); - } -} - -@keyframes accordion-up { - from { - height: var(--bits-accordion-content-height); - } - - to { - height: 0; - } -} - -@keyframes caret-blink { - 0%, - 70%, - 100% { - opacity: 1; - } - - 20%, - 50% { - opacity: 0; - } -} - -@custom-variant data-open { - &:where([data-state='open']), - &:where([data-open]:not([data-open='false'])) { - @slot; - } -} - -@custom-variant data-closed { - &:where([data-state='closed']), - &:where([data-closed]:not([data-closed='false'])) { - @slot; - } -} - -@custom-variant data-checked { - &:where([data-state='checked']), - &:where([data-checked]:not([data-checked='false'])) { - @slot; - } -} - -@custom-variant data-unchecked { - &:where([data-state='unchecked']), - &:where([data-unchecked]:not([data-unchecked='false'])) { - @slot; - } -} - -@custom-variant data-selected { - &:where([data-selected]) { - @slot; - } -} - -@custom-variant data-disabled { - &:where([data-disabled='true']), - &:where([data-disabled]:not([data-disabled='false'])) { - @slot; - } -} - -@custom-variant data-active { - &:where([data-state='active']), - &:where([data-active]:not([data-active='false'])) { - @slot; - } -} - -@custom-variant data-horizontal { - &:where([data-orientation='horizontal']) { - @slot; - } -} - -@custom-variant data-vertical { - &:where([data-orientation='vertical']) { - @slot; - } -} - -@utility no-scrollbar { - -ms-overflow-style: none; - scrollbar-width: none; - &::-webkit-scrollbar { - display: none; - } -} +@import '@openshock/svelte-core/theme.css'; /* driver.js theme override — match the dark UI */ .driver-popover { diff --git a/src/lib/api/firmwareCDN.ts b/src/lib/api/firmwareCDN.ts index a746dc72..0b35efa9 100644 --- a/src/lib/api/firmwareCDN.ts +++ b/src/lib/api/firmwareCDN.ts @@ -1,4 +1,4 @@ -import { HashBuffer } from '$lib/utils/crypto'; +import { HashBuffer } from '$core/utils/crypto'; export const FirmwareChannels = ['stable', 'beta', 'develop'] as const; export type FirmwareChannel = (typeof FirmwareChannels)[number]; diff --git a/src/lib/api/next/transformers/LoginOkResponse.ts b/src/lib/api/next/transformers/LoginOkResponse.ts index 2b4d57d2..19580c86 100644 --- a/src/lib/api/next/transformers/LoginOkResponse.ts +++ b/src/lib/api/next/transformers/LoginOkResponse.ts @@ -1,5 +1,4 @@ -import { isObject } from '$lib/typeguards'; -import { HasBoolean, HasString, HasStringArray } from '../../../typeguards/propGuards'; +import { HasBoolean, HasString, HasStringArray, isObject } from '$core/typeguards'; import { TransformError } from '../TransformError'; import type { LoginOkResponse } from '../models'; import { IsRoleType } from './RoleType'; diff --git a/src/lib/api/next/transformers/OAuthSignupData.ts b/src/lib/api/next/transformers/OAuthSignupData.ts index 9b785e60..d0d78c00 100644 --- a/src/lib/api/next/transformers/OAuthSignupData.ts +++ b/src/lib/api/next/transformers/OAuthSignupData.ts @@ -1,5 +1,4 @@ -import { isObject } from '$lib/typeguards'; -import { HasString, HasStringOrNull } from '../../../typeguards/propGuards'; +import { HasString, HasStringOrNull, isObject } from '$core/typeguards'; import { TransformError } from '../TransformError'; import type { OAuthSignupData } from '../models/OAuthSignupData'; diff --git a/src/lib/api/pwnedPasswords.ts b/src/lib/api/pwnedPasswords.ts deleted file mode 100644 index 5fda02f1..00000000 --- a/src/lib/api/pwnedPasswords.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { HashString } from '$lib/utils/crypto'; - -export async function checkPwnedCount(password: string): Promise { - if (!password) { - throw new Error('Password cannot be empty'); - } - - const hash = await HashString(password, 'SHA-1'); - const hashPrefix = hash.substring(0, 5); - - let raw: string; - try { - const response = await fetch(`https://api.pwnedpasswords.com/range/${hashPrefix}`); - - if (!response.ok) { - throw new Error(`Pwned passwords range request failed with status ${response.status}`); - } - - raw = await response.text(); - } catch (error) { - throw new Error('Error while fetching pwned passwords range', { cause: error }); - } - - const hashSuffix = hash.substring(5).toUpperCase(); - const match = raw.split('\n').find((line) => line.startsWith(hashSuffix)); - - if (match) { - const [, count] = match.split(':'); - - return Number.parseInt(count, 10); - } - - return 0; -} diff --git a/src/lib/components/Code.svelte b/src/lib/components/Code.svelte deleted file mode 100644 index c882be5e..00000000 --- a/src/lib/components/Code.svelte +++ /dev/null @@ -1,13 +0,0 @@ - - - - {@render children?.()} - diff --git a/src/lib/components/ConfirmDeleteDialog.svelte b/src/lib/components/ConfirmDeleteDialog.svelte deleted file mode 100644 index 06faa36f..00000000 --- a/src/lib/components/ConfirmDeleteDialog.svelte +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - {title} - {@render description()} - - {@render children?.()} - - - diff --git a/src/lib/components/Container.svelte b/src/lib/components/Container.svelte deleted file mode 100644 index d8a15ad6..00000000 --- a/src/lib/components/Container.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - -
- {@render children()} -
diff --git a/src/lib/components/ControlModules/LiveButton.svelte b/src/lib/components/ControlModules/LiveButton.svelte index 444c6b93..74fb1940 100644 --- a/src/lib/components/ControlModules/LiveButton.svelte +++ b/src/lib/components/ControlModules/LiveButton.svelte @@ -1,6 +1,6 @@ - -
- {#if icon} - {@render icon()} - {/if} - - - - -
diff --git a/src/lib/components/DotGrid.svelte b/src/lib/components/DotGrid.svelte deleted file mode 100644 index 81580ace..00000000 --- a/src/lib/components/DotGrid.svelte +++ /dev/null @@ -1,51 +0,0 @@ - - -
- - -
- - diff --git a/src/lib/components/EmptyState.svelte b/src/lib/components/EmptyState.svelte deleted file mode 100644 index b3dbbbb0..00000000 --- a/src/lib/components/EmptyState.svelte +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - {title} - {#if description} - - {description} - - {/if} - - {#if children} - - {@render children()} - - {/if} - diff --git a/src/lib/components/ExpirationPicker.svelte b/src/lib/components/ExpirationPicker.svelte index fe3eb504..e4af220f 100644 --- a/src/lib/components/ExpirationPicker.svelte +++ b/src/lib/components/ExpirationPicker.svelte @@ -1,9 +1,9 @@ - - - {@render children?.()} - diff --git a/src/lib/components/LightSwitch.svelte b/src/lib/components/LightSwitch.svelte deleted file mode 100644 index 200f4be8..00000000 --- a/src/lib/components/LightSwitch.svelte +++ /dev/null @@ -1,95 +0,0 @@ - - - pendingScheme !== null, handleOpenChanged}> - - - Switch to light mode - - Warning: You are about to switch to light mode. -
- Are you sure you want to do this? -
-
- -
-
- - - - - - Toggle theme - - - {#each Object.values(ColorScheme) as value (value)} - evaluateLightSwitch(value)}>{value} - {/each} - - diff --git a/src/lib/components/PageHeader.svelte b/src/lib/components/PageHeader.svelte deleted file mode 100644 index f1819e47..00000000 --- a/src/lib/components/PageHeader.svelte +++ /dev/null @@ -1,33 +0,0 @@ - - -
-
-

- {title} -

- {#if children} -
- {@render children()} -
- {/if} -
- - {#if subtitle} -

{subtitle}

- {/if} -
diff --git a/src/lib/components/Stepper.svelte b/src/lib/components/Stepper.svelte index f790092c..0ca9410e 100644 --- a/src/lib/components/Stepper.svelte +++ b/src/lib/components/Stepper.svelte @@ -12,7 +12,7 @@ - - - - {#snippet child({ props })} - - {/snippet} - - - {@render children?.()} - - diff --git a/src/lib/components/TelemetryConsentToast.svelte b/src/lib/components/TelemetryConsentToast.svelte index ea2ddf1c..882d76ea 100644 --- a/src/lib/components/TelemetryConsentToast.svelte +++ b/src/lib/components/TelemetryConsentToast.svelte @@ -1,6 +1,6 @@ - - - - - {date ? df.format(date.toDate()) : 'Pick a date'} - - -
- time && setTime(time)} /> -
- - -
-
diff --git a/src/lib/components/datetime-picker/time-picker-input.svelte b/src/lib/components/datetime-picker/time-picker-input.svelte deleted file mode 100644 index f6a04e56..00000000 --- a/src/lib/components/datetime-picker/time-picker-input.svelte +++ /dev/null @@ -1,140 +0,0 @@ - - - - - { - e.preventDefault(); - onchange?.(e); - }} - {type} - inputmode="decimal" - onkeydown={(e) => { - onkeydown?.(e); - handleKeyDown(e); - }} - {...restProps} -/> diff --git a/src/lib/components/datetime-picker/time-picker-utils.ts b/src/lib/components/datetime-picker/time-picker-utils.ts deleted file mode 100644 index a2d9a498..00000000 --- a/src/lib/components/datetime-picker/time-picker-utils.ts +++ /dev/null @@ -1,190 +0,0 @@ -import { Time } from '@internationalized/date'; - -/** - * regular expression to check for valid hour format (01-23) - */ -export function isValidHour(value: string) { - return /^(0[0-9]|1[0-9]|2[0-3])$/.test(value); -} - -/** - * regular expression to check for valid 12 hour format (01-12) - */ -export function isValid12Hour(value: string) { - return /^(0[1-9]|1[0-2])$/.test(value); -} - -/** - * regular expression to check for valid minute format (00-59) - */ -export function isValidMinuteOrSecond(value: string) { - return /^[0-5][0-9]$/.test(value); -} - -type GetValidNumberConfig = { max: number; min?: number; loop?: boolean }; - -export function getValidNumber( - value: string, - { max, min = 0, loop = false }: GetValidNumberConfig -) { - let numericValue = Number.parseInt(value, 10); - - if (!isNaN(numericValue)) { - if (!loop) { - if (numericValue > max) numericValue = max; - if (numericValue < min) numericValue = min; - } else { - if (numericValue > max) numericValue = min; - if (numericValue < min) numericValue = max; - } - return numericValue.toString().padStart(2, '0'); - } - - return '00'; -} - -export function getValidHour(value: string) { - if (isValidHour(value)) return value; - return getValidNumber(value, { max: 23 }); -} - -export function getValid12Hour(value: string) { - if (isValid12Hour(value)) return value; - return getValidNumber(value, { min: 1, max: 12 }); -} - -export function getValidMinuteOrSecond(value: string) { - if (isValidMinuteOrSecond(value)) return value; - return getValidNumber(value, { max: 59 }); -} - -type GetValidArrowNumberConfig = { - min: number; - max: number; - step: number; -}; - -export function getValidArrowNumber(value: string, { min, max, step }: GetValidArrowNumberConfig) { - let numericValue = Number.parseInt(value, 10); - if (!isNaN(numericValue)) { - numericValue += step; - return getValidNumber(String(numericValue), { min, max, loop: true }); - } - return '00'; -} - -export function getValidArrowHour(value: string, step: number) { - return getValidArrowNumber(value, { min: 0, max: 23, step }); -} - -export function getValidArrow12Hour(value: string, step: number) { - return getValidArrowNumber(value, { min: 1, max: 12, step }); -} - -export function getValidArrowMinuteOrSecond(value: string, step: number) { - return getValidArrowNumber(value, { min: 0, max: 59, step }); -} - -export function setMinutes(time: Time, value: string) { - const minutes = getValidMinuteOrSecond(value); - return time.set({ minute: Number.parseInt(minutes, 10) }); -} - -export function setSeconds(time: Time, value: string) { - const seconds = getValidMinuteOrSecond(value); - return time.set({ second: Number.parseInt(seconds, 10) }); -} - -export function setHours(time: Time, value: string) { - const hours = getValidHour(value); - return time.set({ hour: Number.parseInt(hours, 10) }); -} - -export function set12Hours(time: Time, value: string, period: Period) { - const hours = Number.parseInt(getValid12Hour(value), 10); - const convertedHours = convert12HourTo24Hour(hours, period); - return time.set({ hour: convertedHours }); -} - -export type TimePickerType = 'minutes' | 'seconds' | 'hours' | '12hours'; -export type Period = 'AM' | 'PM'; - -export function setDateByType(time: Time, value: string, type: TimePickerType, period?: Period) { - switch (type) { - case 'minutes': - return setMinutes(time, value); - case 'seconds': - return setSeconds(time, value); - case 'hours': - return setHours(time, value); - case '12hours': { - if (!period) return time; - return set12Hours(time, value, period); - } - default: - return time; - } -} - -export function getDateByType(time: Time, type: TimePickerType) { - switch (type) { - case 'minutes': - return getValidMinuteOrSecond(String(time.minute)); - case 'seconds': - return getValidMinuteOrSecond(String(time.second)); - case 'hours': - return getValidHour(String(time.hour)); - case '12hours': { - const hours = display12HourValue(time.hour); - return getValid12Hour(String(hours)); - } - default: - return '00'; - } -} - -export function getArrowByType(value: string, step: number, type: TimePickerType) { - switch (type) { - case 'minutes': - return getValidArrowMinuteOrSecond(value, step); - case 'seconds': - return getValidArrowMinuteOrSecond(value, step); - case 'hours': - return getValidArrowHour(value, step); - case '12hours': - return getValidArrow12Hour(value, step); - default: - return '00'; - } -} - -/** - * handles value change of 12-hour input - * 12:00 PM is 12:00 - * 12:00 AM is 00:00 - */ -export function convert12HourTo24Hour(hour: number, period: Period) { - if (period === 'PM') { - if (hour <= 11) { - return hour + 12; - } else { - return hour; - } - } else if (period === 'AM') { - if (hour === 12) return 0; - return hour; - } - return hour; -} - -/** - * time is stored in the 24-hour form, - * but needs to be displayed to the user - * in its 12-hour representation - */ -export function display12HourValue(hours: number) { - if (hours === 0 || hours === 12) return '12'; - if (hours >= 22) return `${hours - 12}`; - if (hours % 12 > 9) return `${hours}`; - return `0${hours % 12}`; -} diff --git a/src/lib/components/datetime-picker/time-picker.svelte b/src/lib/components/datetime-picker/time-picker.svelte deleted file mode 100644 index a0ee4afe..00000000 --- a/src/lib/components/datetime-picker/time-picker.svelte +++ /dev/null @@ -1,83 +0,0 @@ - - -
-
- {#if view === 'labels'} - - {/if} - - minuteRef?.focus()} - /> -
- - {#if view === 'dotted'} - : - {/if} - -
- {#if view === 'labels'} - - {/if} - - hourRef?.focus()} - onRightFocus={() => secondRef?.focus()} - /> -
- - {#if view === 'dotted'} - : - {/if} - - {#if showSeconds} -
- {#if view === 'labels'} - - {/if} - - minuteRef?.focus()} - /> -
- {/if} -
diff --git a/src/lib/components/dialog-manager/dialog-alert-content.svelte b/src/lib/components/dialog-manager/dialog-alert-content.svelte deleted file mode 100644 index e8b4ea1f..00000000 --- a/src/lib/components/dialog-manager/dialog-alert-content.svelte +++ /dev/null @@ -1,21 +0,0 @@ - - - - {title} - {#if desc} - {desc} - {/if} - - - - diff --git a/src/lib/components/dialog-manager/dialog-confirm-content.svelte b/src/lib/components/dialog-manager/dialog-confirm-content.svelte deleted file mode 100644 index 450b7556..00000000 --- a/src/lib/components/dialog-manager/dialog-confirm-content.svelte +++ /dev/null @@ -1,45 +0,0 @@ - - - - {title} - - {desc} - {#if descSnippet} - {@render descSnippet(data as T)} - {/if} - - - - - - diff --git a/src/lib/components/dialog-manager/dialog-custom-content.svelte b/src/lib/components/dialog-manager/dialog-custom-content.svelte deleted file mode 100644 index 38f91730..00000000 --- a/src/lib/components/dialog-manager/dialog-custom-content.svelte +++ /dev/null @@ -1,16 +0,0 @@ - - -{@render contentSnippet(renderProps)} diff --git a/src/lib/components/dialog-manager/dialog-manager.svelte b/src/lib/components/dialog-manager/dialog-manager.svelte deleted file mode 100644 index 5d4749c0..00000000 --- a/src/lib/components/dialog-manager/dialog-manager.svelte +++ /dev/null @@ -1,35 +0,0 @@ - - -{#if dialogId && ctx} - {#key dialogId} - open, handleOpenChange}> - - - - - {/key} -{/if} diff --git a/src/lib/components/dialog-manager/dialog-store.svelte.ts b/src/lib/components/dialog-manager/dialog-store.svelte.ts deleted file mode 100644 index ce520d2d..00000000 --- a/src/lib/components/dialog-manager/dialog-store.svelte.ts +++ /dev/null @@ -1,96 +0,0 @@ -import { SvelteMap } from 'svelte/reactivity'; -import DialogAlertContent from './dialog-alert-content.svelte'; -import DialogConfirmContent from './dialog-confirm-content.svelte'; -import DialogCustomContent from './dialog-custom-content.svelte'; -import type { - AlertDialogOptions, - ConfirmDialogOptions, - ConfirmResult, - CustomDialogOptions, - DialogContext, -} from './types'; - -// State -let dialogCount = $state(0); -const dialogs = new SvelteMap(); - -export function getOldestDialog(): [number, DialogContext] | null { - const firstEntry = dialogs.entries().next(); - return firstEntry.done ? null : firstEntry.value; -} - -export function removeDialog(id: number): void { - dialogs.delete(id); -} - -// Helper to create dialog with common setup -export function createDialog( - contextFactory: (resolve: (result: R) => void) => DialogContext -): Promise { - const { promise, resolve } = Promise.withResolvers(); - const id = ++dialogCount; - let resolved = false; - - const wrappedResolve = (result: R) => { - if (resolved) return; - resolved = true; - setTimeout(() => removeDialog(id), 150); - resolve(result); - }; - - dialogs.set(id, contextFactory(wrappedResolve) as DialogContext); - return promise; -} - -/** - * Opens a fully custom dialog with your own content snippet. - */ -export function open(options: CustomDialogOptions): Promise { - return createDialog((resolve) => ({ - content: DialogCustomContent, - props: { - data: options.data, - contentSnippet: options.contentSnippet, - resolve, - close: () => resolve(undefined as R), - }, - resolve, - })); -} - -/** - * Opens a confirm dialog with built-in confirm/cancel buttons. - */ -export function confirm(options: ConfirmDialogOptions): Promise> { - return createDialog>((resolve) => ({ - content: DialogConfirmContent, - props: { - ...options, - resolve, - close: () => resolve({ confirmed: false }), - }, - resolve, - })); -} - -/** - * Opens an alert dialog that the user acknowledges. - */ -export function alert(options: AlertDialogOptions): Promise { - return createDialog((resolve) => ({ - content: DialogAlertContent, - props: { - ...options, - resolve, - close: () => resolve(), - }, - resolve, - })); -} - -export const dialog = { - open, - confirm, - alert, - createDialog, -}; diff --git a/src/lib/components/dialog-manager/types.ts b/src/lib/components/dialog-manager/types.ts deleted file mode 100644 index b234e297..00000000 --- a/src/lib/components/dialog-manager/types.ts +++ /dev/null @@ -1,59 +0,0 @@ -import type { AnyComponent } from '$lib/types/AnyComponent'; -import type { Snippet } from 'svelte'; - -// Props passed to dialog content components -export interface DialogContentProps { - resolve: (result: R) => void; - close: () => void; -} - -// Props for custom dialog snippets -export interface DialogRenderProps extends DialogContentProps { - data: T; -} - -// Generic dialog context - stores a component to render -export interface DialogContext { - content: AnyComponent; - props: Record; - resolve: (result: R) => void; -} - -// Result types -export type ConfirmResult = { confirmed: true; data: T } | { confirmed: false }; - -// Options for each dialog type -export interface CustomDialogOptions { - data?: T; - contentSnippet: Snippet<[DialogRenderProps]>; -} - -export interface ConfirmDialogOptions { - title: string; - desc?: string; - data?: T; - confirmButtonText?: string; - cancelButtonText?: string; - descSnippet?: Snippet<[T]>; -} - -export interface AlertDialogOptions { - title: string; - desc?: string; - buttonText?: string; -} - -export interface AlertProps extends AlertDialogOptions { - resolve: () => void; - close: () => void; -} - -export interface ConfirmProps extends ConfirmDialogOptions { - resolve: (result: ConfirmResult) => void; - close: () => void; -} - -export interface CustomProps extends CustomDialogOptions { - resolve: (result: R) => void; - close: () => void; -} diff --git a/src/lib/components/input/DatePicker.svelte b/src/lib/components/input/DatePicker.svelte index 762d4cd1..bfaf878f 100644 --- a/src/lib/components/input/DatePicker.svelte +++ b/src/lib/components/input/DatePicker.svelte @@ -1,10 +1,10 @@ - - diff --git a/src/lib/components/input/PasswordInput.svelte b/src/lib/components/input/PasswordInput.svelte deleted file mode 100644 index d7a8a8a5..00000000 --- a/src/lib/components/input/PasswordInput.svelte +++ /dev/null @@ -1,161 +0,0 @@ - - -{#snippet popup()} - -{/snippet} - - (showPopup = false)} - popup={showPopup ? (popup as Snippet) : undefined} -> - {#snippet labelSnippet(id: string)} -
- {label} - {#if showForget} - - Forgot your password? - - {/if} -
- {/snippet} - {#snippet after()} - - {/snippet} -
diff --git a/src/lib/components/input/TextInput.svelte b/src/lib/components/input/TextInput.svelte deleted file mode 100644 index a3692017..00000000 --- a/src/lib/components/input/TextInput.svelte +++ /dev/null @@ -1,130 +0,0 @@ - - - - {#if labelSnippet} - {@render labelSnippet(id)} - {/if} - - {#if label} - {label} - {/if} - -
- {#if Icon} - - {/if} - {#if after} - - - - {@render after()} - - - {:else} - - {/if} - {#if popup} - - {/if} -
- {#if validationResult?.message} -

- {validationResult.message} - {#if validationResult.link} - - - {validationResult.link.text} - - {/if} -

- {:else} - - {/if} -
diff --git a/src/lib/components/input/UsernameInput.svelte b/src/lib/components/input/UsernameInput.svelte index 151536fa..72ae78d1 100644 --- a/src/lib/components/input/UsernameInput.svelte +++ b/src/lib/components/input/UsernameInput.svelte @@ -1,6 +1,6 @@ - - diff --git a/src/lib/components/metadata/BasicTags.svelte b/src/lib/components/metadata/BasicTags.svelte deleted file mode 100644 index 3f84afc0..00000000 --- a/src/lib/components/metadata/BasicTags.svelte +++ /dev/null @@ -1,15 +0,0 @@ - - - - {title} - {#if description} - - {/if} - diff --git a/src/lib/components/metadata/OpenGraphTags.svelte b/src/lib/components/metadata/OpenGraphTags.svelte deleted file mode 100644 index a08887f9..00000000 --- a/src/lib/components/metadata/OpenGraphTags.svelte +++ /dev/null @@ -1,106 +0,0 @@ - - - - - - - - {#if image.type} - - {/if} - {#if image.width} - - {/if} - {#if image.height} - - {/if} - {#if image.alt} - - {/if} - - - {#if siteName} - - {/if} - {#if description} - - {/if} - {#if determiner} - - {/if} - - {#if metaLocale} - - {/if} - {#if locales} - {#each locales as locale (locale)} - - {/each} - {/if} - - {#if video} - - {#if video.type} - - {/if} - {#if video.width} - - {/if} - {#if video.height} - - {/if} - {/if} - - {#if audio} - - {#if audio.type} - - {/if} - {/if} - diff --git a/src/lib/components/metadata/Twitter/TwitterAppTags.svelte b/src/lib/components/metadata/Twitter/TwitterAppTags.svelte deleted file mode 100644 index 860175ff..00000000 --- a/src/lib/components/metadata/Twitter/TwitterAppTags.svelte +++ /dev/null @@ -1,32 +0,0 @@ - - - - - {#if site} - - {/if} - {#if iphone} - - - - {/if} - {#if ipad} - - - - {/if} - {#if googleplay} - - - - {/if} - diff --git a/src/lib/components/metadata/Twitter/TwitterPlayerTags.svelte b/src/lib/components/metadata/Twitter/TwitterPlayerTags.svelte deleted file mode 100644 index ca046631..00000000 --- a/src/lib/components/metadata/Twitter/TwitterPlayerTags.svelte +++ /dev/null @@ -1,44 +0,0 @@ - - - - - {#if site} - {#if isTwitterHandle(site)} - - {:else} - - {/if} - {/if} - {#if description} - - {/if} - {#if title} - - {/if} - {#if image} - - - {/if} - {#if player} - {#if player.type === 'iframe'} - - {/if} - - - {#if player.type === 'stream'} - - {/if} - {/if} - diff --git a/src/lib/components/metadata/Twitter/TwitterSummaryTags.svelte b/src/lib/components/metadata/Twitter/TwitterSummaryTags.svelte deleted file mode 100644 index 7c8286b1..00000000 --- a/src/lib/components/metadata/Twitter/TwitterSummaryTags.svelte +++ /dev/null @@ -1,42 +0,0 @@ - - - - - {#if site} - {#if isTwitterHandle(site)} - - {:else} - - {/if} - {/if} - {#if creator} - {#if isTwitterHandle(creator)} - - {:else} - - {/if} - {/if} - {#if description} - - {/if} - {#if title} - - {/if} - {#if image} - - - {/if} - diff --git a/src/lib/components/metadata/Twitter/index.ts b/src/lib/components/metadata/Twitter/index.ts deleted file mode 100644 index dea413e3..00000000 --- a/src/lib/components/metadata/Twitter/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -import TwitterAppTags from './TwitterAppTags.svelte'; -import TwitterPlayerTags from './TwitterPlayerTags.svelte'; -import TwitterSummaryTags from './TwitterSummaryTags.svelte'; - -export { TwitterAppTags, TwitterPlayerTags, TwitterSummaryTags }; diff --git a/src/lib/components/metadata/index.ts b/src/lib/components/metadata/index.ts deleted file mode 100644 index fc6adc3f..00000000 --- a/src/lib/components/metadata/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -import BasicTags from './BasicTags.svelte'; -import OpenGraphTags from './OpenGraphTags.svelte'; -import { TwitterAppTags, TwitterPlayerTags, TwitterSummaryTags } from './Twitter'; - -export { BasicTags, OpenGraphTags, TwitterAppTags, TwitterPlayerTags, TwitterSummaryTags }; diff --git a/src/lib/components/shares/permission-tooltip.svelte b/src/lib/components/shares/permission-tooltip.svelte index 8d335658..50e70643 100644 --- a/src/lib/components/shares/permission-tooltip.svelte +++ b/src/lib/components/shares/permission-tooltip.svelte @@ -1,7 +1,7 @@ - - - - - Google Chrome - - - - - - - - - - - - - - - - - - - - diff --git a/src/lib/components/svg/CloudflareLogo.svelte b/src/lib/components/svg/CloudflareLogo.svelte deleted file mode 100644 index 3bc70c30..00000000 --- a/src/lib/components/svg/CloudflareLogo.svelte +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - Cloudflare - - - - - - - - - - - - - - - diff --git a/src/lib/components/svg/DiscordLogo.svelte b/src/lib/components/svg/DiscordLogo.svelte deleted file mode 100644 index b8858fbd..00000000 --- a/src/lib/components/svg/DiscordLogo.svelte +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - Discord - - diff --git a/src/lib/components/svg/EdgeLogo.svelte b/src/lib/components/svg/EdgeLogo.svelte deleted file mode 100644 index bd406c8f..00000000 --- a/src/lib/components/svg/EdgeLogo.svelte +++ /dev/null @@ -1,126 +0,0 @@ - - - - - - Microsoft Edge - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/lib/components/svg/GithubIcon.svelte b/src/lib/components/svg/GithubIcon.svelte deleted file mode 100644 index d6882d0c..00000000 --- a/src/lib/components/svg/GithubIcon.svelte +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - Github - - diff --git a/src/lib/components/svg/GoogleLogo.svelte b/src/lib/components/svg/GoogleLogo.svelte deleted file mode 100644 index 84040e23..00000000 --- a/src/lib/components/svg/GoogleLogo.svelte +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - Google - - diff --git a/src/lib/components/svg/LiveControlIcon.svelte b/src/lib/components/svg/LiveControlIcon.svelte index 0e0399ea..fbf11ea2 100644 --- a/src/lib/components/svg/LiveControlIcon.svelte +++ b/src/lib/components/svg/LiveControlIcon.svelte @@ -1,5 +1,5 @@ - - - - - Opera - - - - - - - - - - - - - - - - - - diff --git a/src/lib/components/svg/XLogo.svelte b/src/lib/components/svg/XLogo.svelte deleted file mode 100644 index 256c4da8..00000000 --- a/src/lib/components/svg/XLogo.svelte +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - X (formerly Twitter) - - diff --git a/src/lib/components/ui/README.md b/src/lib/components/ui/README.md deleted file mode 100644 index 42223f18..00000000 --- a/src/lib/components/ui/README.md +++ /dev/null @@ -1,47 +0,0 @@ -# Updating shadcn-svelte Components - -Everything in this directory comes from the shadcn-svelte registry **except** `multi-select-combobox`. - -## How to Update - -Run the update script from the project root: - -```bash -./scripts/update-shadcn.sh -``` - -This will automatically: -1. Delete all shadcn component directories (preserving `multi-select-combobox`) -2. Re-add them from the registry -3. Remove unwanted dependencies the CLI adds -4. Upgrade all dependencies to latest -5. Reapply project-specific customizations (see below) -6. Format and type-check the result - -Review the git diff before committing. - -## Custom Modifications - -These are automatically applied by the script, but documented here for reference. - -### Sidebar (`sidebar.svelte`) - -- Change `ease-linear` to `ease-in-out` -- Change `duration-200` to `duration-300` - -### Sidebar submenu (`sidebar-menu-sub.svelte`) - -- Change `mx-3.5` to `ml-3.5` -- Change `px-2.5` to `pl-2.5` - -### Sonner (`sonner.svelte`) - -- Uses our own `color-scheme-state` instead of `mode-watcher` - -### Slider (`slider.svelte`) - -- Add `cursor-w-resize` to the thumb - -### Toggle group (`toggle-group.svelte`) - -- Add `// svelte-ignore state_referenced_locally` to suppress false warnings diff --git a/src/lib/components/ui/accordion/accordion-content.svelte b/src/lib/components/ui/accordion/accordion-content.svelte deleted file mode 100644 index 7360caf5..00000000 --- a/src/lib/components/ui/accordion/accordion-content.svelte +++ /dev/null @@ -1,27 +0,0 @@ - - - -
- {@render children?.()} -
-
diff --git a/src/lib/components/ui/accordion/accordion-item.svelte b/src/lib/components/ui/accordion/accordion-item.svelte deleted file mode 100644 index e2b299fe..00000000 --- a/src/lib/components/ui/accordion/accordion-item.svelte +++ /dev/null @@ -1,17 +0,0 @@ - - - diff --git a/src/lib/components/ui/accordion/accordion-trigger.svelte b/src/lib/components/ui/accordion/accordion-trigger.svelte deleted file mode 100644 index cdff46f1..00000000 --- a/src/lib/components/ui/accordion/accordion-trigger.svelte +++ /dev/null @@ -1,32 +0,0 @@ - - - - - {@render children?.()} - - - diff --git a/src/lib/components/ui/accordion/accordion.svelte b/src/lib/components/ui/accordion/accordion.svelte deleted file mode 100644 index 01ee847d..00000000 --- a/src/lib/components/ui/accordion/accordion.svelte +++ /dev/null @@ -1,19 +0,0 @@ - - - diff --git a/src/lib/components/ui/accordion/index.ts b/src/lib/components/ui/accordion/index.ts deleted file mode 100644 index ac343a10..00000000 --- a/src/lib/components/ui/accordion/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -import Root from "./accordion.svelte"; -import Content from "./accordion-content.svelte"; -import Item from "./accordion-item.svelte"; -import Trigger from "./accordion-trigger.svelte"; - -export { - Root, - Content, - Item, - Trigger, - // - Root as Accordion, - Content as AccordionContent, - Item as AccordionItem, - Trigger as AccordionTrigger, -}; diff --git a/src/lib/components/ui/avatar/avatar-badge.svelte b/src/lib/components/ui/avatar/avatar-badge.svelte deleted file mode 100644 index d64ff149..00000000 --- a/src/lib/components/ui/avatar/avatar-badge.svelte +++ /dev/null @@ -1,26 +0,0 @@ - - -svg]:hidden", - "group-data-[size=default]/avatar:size-2.5 group-data-[size=default]/avatar:[&>svg]:size-2", - "group-data-[size=lg]/avatar:size-3 group-data-[size=lg]/avatar:[&>svg]:size-2", - className - )} - {...restProps} -> - {@render children?.()} - diff --git a/src/lib/components/ui/avatar/avatar-fallback.svelte b/src/lib/components/ui/avatar/avatar-fallback.svelte deleted file mode 100644 index 3b7a6e30..00000000 --- a/src/lib/components/ui/avatar/avatar-fallback.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - - diff --git a/src/lib/components/ui/avatar/avatar-group-count.svelte b/src/lib/components/ui/avatar/avatar-group-count.svelte deleted file mode 100644 index c1283ffc..00000000 --- a/src/lib/components/ui/avatar/avatar-group-count.svelte +++ /dev/null @@ -1,23 +0,0 @@ - - -
svg]:size-4 group-has-data-[size=lg]/avatar-group:[&>svg]:size-5 group-has-data-[size=sm]/avatar-group:[&>svg]:size-3 ring-background relative flex shrink-0 items-center justify-center ring-2", - className - )} - {...restProps} -> - {@render children?.()} -
diff --git a/src/lib/components/ui/avatar/avatar-group.svelte b/src/lib/components/ui/avatar/avatar-group.svelte deleted file mode 100644 index cec81e54..00000000 --- a/src/lib/components/ui/avatar/avatar-group.svelte +++ /dev/null @@ -1,23 +0,0 @@ - - -
- {@render children?.()} -
diff --git a/src/lib/components/ui/avatar/avatar-image.svelte b/src/lib/components/ui/avatar/avatar-image.svelte deleted file mode 100644 index 910a3378..00000000 --- a/src/lib/components/ui/avatar/avatar-image.svelte +++ /dev/null @@ -1,17 +0,0 @@ - - - diff --git a/src/lib/components/ui/avatar/avatar.svelte b/src/lib/components/ui/avatar/avatar.svelte deleted file mode 100644 index 5a1f954b..00000000 --- a/src/lib/components/ui/avatar/avatar.svelte +++ /dev/null @@ -1,26 +0,0 @@ - - - diff --git a/src/lib/components/ui/avatar/index.ts b/src/lib/components/ui/avatar/index.ts deleted file mode 100644 index 38ccef84..00000000 --- a/src/lib/components/ui/avatar/index.ts +++ /dev/null @@ -1,22 +0,0 @@ -import Root from "./avatar.svelte"; -import Image from "./avatar-image.svelte"; -import Fallback from "./avatar-fallback.svelte"; -import Badge from "./avatar-badge.svelte"; -import Group from "./avatar-group.svelte"; -import GroupCount from "./avatar-group-count.svelte"; - -export { - Root, - Image, - Fallback, - Badge, - Group, - GroupCount, - // - Root as Avatar, - Image as AvatarImage, - Fallback as AvatarFallback, - Badge as AvatarBadge, - Group as AvatarGroup, - GroupCount as AvatarGroupCount, -}; diff --git a/src/lib/components/ui/badge/badge.svelte b/src/lib/components/ui/badge/badge.svelte deleted file mode 100644 index 26281952..00000000 --- a/src/lib/components/ui/badge/badge.svelte +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - {@render children?.()} - diff --git a/src/lib/components/ui/badge/index.ts b/src/lib/components/ui/badge/index.ts deleted file mode 100644 index 64e0aa9b..00000000 --- a/src/lib/components/ui/badge/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default as Badge } from "./badge.svelte"; -export { badgeVariants, type BadgeVariant } from "./badge.svelte"; diff --git a/src/lib/components/ui/breadcrumb/breadcrumb-ellipsis.svelte b/src/lib/components/ui/breadcrumb/breadcrumb-ellipsis.svelte deleted file mode 100644 index 28d78fd0..00000000 --- a/src/lib/components/ui/breadcrumb/breadcrumb-ellipsis.svelte +++ /dev/null @@ -1,23 +0,0 @@ - - - diff --git a/src/lib/components/ui/breadcrumb/breadcrumb-item.svelte b/src/lib/components/ui/breadcrumb/breadcrumb-item.svelte deleted file mode 100644 index ecd73f9d..00000000 --- a/src/lib/components/ui/breadcrumb/breadcrumb-item.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - -
  • - {@render children?.()} -
  • diff --git a/src/lib/components/ui/breadcrumb/breadcrumb-link.svelte b/src/lib/components/ui/breadcrumb/breadcrumb-link.svelte deleted file mode 100644 index 42da73fd..00000000 --- a/src/lib/components/ui/breadcrumb/breadcrumb-link.svelte +++ /dev/null @@ -1,31 +0,0 @@ - - -{#if child} - {@render child({ props: attrs })} -{:else} - - {@render children?.()} - -{/if} diff --git a/src/lib/components/ui/breadcrumb/breadcrumb-list.svelte b/src/lib/components/ui/breadcrumb/breadcrumb-list.svelte deleted file mode 100644 index 4edc2636..00000000 --- a/src/lib/components/ui/breadcrumb/breadcrumb-list.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - -
      - {@render children?.()} -
    diff --git a/src/lib/components/ui/breadcrumb/breadcrumb-page.svelte b/src/lib/components/ui/breadcrumb/breadcrumb-page.svelte deleted file mode 100644 index 8e371964..00000000 --- a/src/lib/components/ui/breadcrumb/breadcrumb-page.svelte +++ /dev/null @@ -1,23 +0,0 @@ - - - - {@render children?.()} - diff --git a/src/lib/components/ui/breadcrumb/breadcrumb-separator.svelte b/src/lib/components/ui/breadcrumb/breadcrumb-separator.svelte deleted file mode 100644 index 7d870b5f..00000000 --- a/src/lib/components/ui/breadcrumb/breadcrumb-separator.svelte +++ /dev/null @@ -1,27 +0,0 @@ - - - diff --git a/src/lib/components/ui/breadcrumb/breadcrumb.svelte b/src/lib/components/ui/breadcrumb/breadcrumb.svelte deleted file mode 100644 index 78fc5209..00000000 --- a/src/lib/components/ui/breadcrumb/breadcrumb.svelte +++ /dev/null @@ -1,22 +0,0 @@ - - - diff --git a/src/lib/components/ui/breadcrumb/index.ts b/src/lib/components/ui/breadcrumb/index.ts deleted file mode 100644 index dc914ec3..00000000 --- a/src/lib/components/ui/breadcrumb/index.ts +++ /dev/null @@ -1,25 +0,0 @@ -import Root from "./breadcrumb.svelte"; -import Ellipsis from "./breadcrumb-ellipsis.svelte"; -import Item from "./breadcrumb-item.svelte"; -import Separator from "./breadcrumb-separator.svelte"; -import Link from "./breadcrumb-link.svelte"; -import List from "./breadcrumb-list.svelte"; -import Page from "./breadcrumb-page.svelte"; - -export { - Root, - Ellipsis, - Item, - Separator, - Link, - List, - Page, - // - Root as Breadcrumb, - Ellipsis as BreadcrumbEllipsis, - Item as BreadcrumbItem, - Separator as BreadcrumbSeparator, - Link as BreadcrumbLink, - List as BreadcrumbList, - Page as BreadcrumbPage, -}; diff --git a/src/lib/components/ui/button/button.svelte b/src/lib/components/ui/button/button.svelte deleted file mode 100644 index a2f724d8..00000000 --- a/src/lib/components/ui/button/button.svelte +++ /dev/null @@ -1,82 +0,0 @@ - - - - -{#if href} - - {@render children?.()} - -{:else} - -{/if} diff --git a/src/lib/components/ui/button/index.ts b/src/lib/components/ui/button/index.ts deleted file mode 100644 index fb585d76..00000000 --- a/src/lib/components/ui/button/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -import Root, { - type ButtonProps, - type ButtonSize, - type ButtonVariant, - buttonVariants, -} from "./button.svelte"; - -export { - Root, - type ButtonProps as Props, - // - Root as Button, - buttonVariants, - type ButtonProps, - type ButtonSize, - type ButtonVariant, -}; diff --git a/src/lib/components/ui/calendar/calendar-caption.svelte b/src/lib/components/ui/calendar/calendar-caption.svelte deleted file mode 100644 index 5c930370..00000000 --- a/src/lib/components/ui/calendar/calendar-caption.svelte +++ /dev/null @@ -1,76 +0,0 @@ - - -{#snippet MonthSelect()} - { - if (!placeholder) return; - const v = Number.parseInt(e.currentTarget.value); - const newPlaceholder = placeholder.set({ month: v }); - placeholder = newPlaceholder.subtract({ months: monthIndex }); - }} - /> -{/snippet} - -{#snippet YearSelect()} - -{/snippet} - -{#if captionLayout === "dropdown"} - {@render MonthSelect()} - {@render YearSelect()} -{:else if captionLayout === "dropdown-months"} - {@render MonthSelect()} - {#if placeholder} - {formatYear(placeholder)} - {/if} -{:else if captionLayout === "dropdown-years"} - {#if placeholder} - {formatMonth(placeholder)} - {/if} - {@render YearSelect()} -{:else} - {formatMonth(month)} {formatYear(month)} -{/if} diff --git a/src/lib/components/ui/calendar/calendar-cell.svelte b/src/lib/components/ui/calendar/calendar-cell.svelte deleted file mode 100644 index c02eeab1..00000000 --- a/src/lib/components/ui/calendar/calendar-cell.svelte +++ /dev/null @@ -1,19 +0,0 @@ - - - diff --git a/src/lib/components/ui/calendar/calendar-day.svelte b/src/lib/components/ui/calendar/calendar-day.svelte deleted file mode 100644 index be3599d5..00000000 --- a/src/lib/components/ui/calendar/calendar-day.svelte +++ /dev/null @@ -1,33 +0,0 @@ - - -span]:text-xs [&>span]:opacity-70", - className - )} - {...restProps} -/> diff --git a/src/lib/components/ui/calendar/calendar-grid-body.svelte b/src/lib/components/ui/calendar/calendar-grid-body.svelte deleted file mode 100644 index 6f6185fc..00000000 --- a/src/lib/components/ui/calendar/calendar-grid-body.svelte +++ /dev/null @@ -1,12 +0,0 @@ - - - diff --git a/src/lib/components/ui/calendar/calendar-grid-head.svelte b/src/lib/components/ui/calendar/calendar-grid-head.svelte deleted file mode 100644 index 58b44b01..00000000 --- a/src/lib/components/ui/calendar/calendar-grid-head.svelte +++ /dev/null @@ -1,12 +0,0 @@ - - - diff --git a/src/lib/components/ui/calendar/calendar-grid-row.svelte b/src/lib/components/ui/calendar/calendar-grid-row.svelte deleted file mode 100644 index 002470ca..00000000 --- a/src/lib/components/ui/calendar/calendar-grid-row.svelte +++ /dev/null @@ -1,12 +0,0 @@ - - - diff --git a/src/lib/components/ui/calendar/calendar-grid.svelte b/src/lib/components/ui/calendar/calendar-grid.svelte deleted file mode 100644 index fc0875e6..00000000 --- a/src/lib/components/ui/calendar/calendar-grid.svelte +++ /dev/null @@ -1,16 +0,0 @@ - - - diff --git a/src/lib/components/ui/calendar/calendar-head-cell.svelte b/src/lib/components/ui/calendar/calendar-head-cell.svelte deleted file mode 100644 index 475b4e35..00000000 --- a/src/lib/components/ui/calendar/calendar-head-cell.svelte +++ /dev/null @@ -1,19 +0,0 @@ - - - diff --git a/src/lib/components/ui/calendar/calendar-header.svelte b/src/lib/components/ui/calendar/calendar-header.svelte deleted file mode 100644 index b3bc4a0a..00000000 --- a/src/lib/components/ui/calendar/calendar-header.svelte +++ /dev/null @@ -1,19 +0,0 @@ - - - diff --git a/src/lib/components/ui/calendar/calendar-heading.svelte b/src/lib/components/ui/calendar/calendar-heading.svelte deleted file mode 100644 index 0c3ea1a3..00000000 --- a/src/lib/components/ui/calendar/calendar-heading.svelte +++ /dev/null @@ -1,16 +0,0 @@ - - - diff --git a/src/lib/components/ui/calendar/calendar-month-select.svelte b/src/lib/components/ui/calendar/calendar-month-select.svelte deleted file mode 100644 index 1545241d..00000000 --- a/src/lib/components/ui/calendar/calendar-month-select.svelte +++ /dev/null @@ -1,48 +0,0 @@ - - - - - {#snippet child({ props, monthItems, selectedMonthItem })} - - - {/snippet} - - diff --git a/src/lib/components/ui/calendar/calendar-month.svelte b/src/lib/components/ui/calendar/calendar-month.svelte deleted file mode 100644 index 34bb5ec2..00000000 --- a/src/lib/components/ui/calendar/calendar-month.svelte +++ /dev/null @@ -1,15 +0,0 @@ - - -
    - {@render children?.()} -
    diff --git a/src/lib/components/ui/calendar/calendar-months.svelte b/src/lib/components/ui/calendar/calendar-months.svelte deleted file mode 100644 index 8125cdc4..00000000 --- a/src/lib/components/ui/calendar/calendar-months.svelte +++ /dev/null @@ -1,19 +0,0 @@ - - -
    - {@render children?.()} -
    diff --git a/src/lib/components/ui/calendar/calendar-nav.svelte b/src/lib/components/ui/calendar/calendar-nav.svelte deleted file mode 100644 index c0e99a77..00000000 --- a/src/lib/components/ui/calendar/calendar-nav.svelte +++ /dev/null @@ -1,19 +0,0 @@ - - - diff --git a/src/lib/components/ui/calendar/calendar-next-button.svelte b/src/lib/components/ui/calendar/calendar-next-button.svelte deleted file mode 100644 index c507d6b1..00000000 --- a/src/lib/components/ui/calendar/calendar-next-button.svelte +++ /dev/null @@ -1,36 +0,0 @@ - - -{#snippet Fallback()} - -{/snippet} - - - {#if children} - {@render children?.()} - {:else} - {@render Fallback()} - {/if} - diff --git a/src/lib/components/ui/calendar/calendar-prev-button.svelte b/src/lib/components/ui/calendar/calendar-prev-button.svelte deleted file mode 100644 index 3d6b5549..00000000 --- a/src/lib/components/ui/calendar/calendar-prev-button.svelte +++ /dev/null @@ -1,36 +0,0 @@ - - -{#snippet Fallback()} - -{/snippet} - - - {#if children} - {@render children?.()} - {:else} - {@render Fallback()} - {/if} - diff --git a/src/lib/components/ui/calendar/calendar-year-select.svelte b/src/lib/components/ui/calendar/calendar-year-select.svelte deleted file mode 100644 index 5956ddd8..00000000 --- a/src/lib/components/ui/calendar/calendar-year-select.svelte +++ /dev/null @@ -1,47 +0,0 @@ - - - - - {#snippet child({ props, yearItems, selectedYearItem })} - - - {/snippet} - - diff --git a/src/lib/components/ui/calendar/calendar.svelte b/src/lib/components/ui/calendar/calendar.svelte deleted file mode 100644 index c70552c0..00000000 --- a/src/lib/components/ui/calendar/calendar.svelte +++ /dev/null @@ -1,115 +0,0 @@ - - - - - {#snippet children({ months, weekdays })} - - - - - - {#each months as month, monthIndex (month)} - - - - - - - - {#each weekdays as weekday, i (i)} - - {weekday.slice(0, 2)} - - {/each} - - - - {#each month.weeks as weekDates (weekDates)} - - {#each weekDates as date (date)} - - {#if day} - {@render day({ - day: date, - outsideMonth: !isEqualMonth(date, month.value), - })} - {:else} - - {/if} - - {/each} - - {/each} - - - - {/each} - - {/snippet} - diff --git a/src/lib/components/ui/calendar/index.ts b/src/lib/components/ui/calendar/index.ts deleted file mode 100644 index f3a16d2d..00000000 --- a/src/lib/components/ui/calendar/index.ts +++ /dev/null @@ -1,40 +0,0 @@ -import Root from "./calendar.svelte"; -import Cell from "./calendar-cell.svelte"; -import Day from "./calendar-day.svelte"; -import Grid from "./calendar-grid.svelte"; -import Header from "./calendar-header.svelte"; -import Months from "./calendar-months.svelte"; -import GridRow from "./calendar-grid-row.svelte"; -import Heading from "./calendar-heading.svelte"; -import GridBody from "./calendar-grid-body.svelte"; -import GridHead from "./calendar-grid-head.svelte"; -import HeadCell from "./calendar-head-cell.svelte"; -import NextButton from "./calendar-next-button.svelte"; -import PrevButton from "./calendar-prev-button.svelte"; -import MonthSelect from "./calendar-month-select.svelte"; -import YearSelect from "./calendar-year-select.svelte"; -import Month from "./calendar-month.svelte"; -import Nav from "./calendar-nav.svelte"; -import Caption from "./calendar-caption.svelte"; - -export { - Day, - Cell, - Grid, - Header, - Months, - GridRow, - Heading, - GridBody, - GridHead, - HeadCell, - NextButton, - PrevButton, - Nav, - Month, - YearSelect, - MonthSelect, - Caption, - // - Root as Calendar, -}; diff --git a/src/lib/components/ui/card/card-action.svelte b/src/lib/components/ui/card/card-action.svelte deleted file mode 100644 index d49f1c34..00000000 --- a/src/lib/components/ui/card/card-action.svelte +++ /dev/null @@ -1,23 +0,0 @@ - - -
    - {@render children?.()} -
    diff --git a/src/lib/components/ui/card/card-content.svelte b/src/lib/components/ui/card/card-content.svelte deleted file mode 100644 index f3a4ace2..00000000 --- a/src/lib/components/ui/card/card-content.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - -
    - {@render children?.()} -
    diff --git a/src/lib/components/ui/card/card-description.svelte b/src/lib/components/ui/card/card-description.svelte deleted file mode 100644 index 9449ce62..00000000 --- a/src/lib/components/ui/card/card-description.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - -

    - {@render children?.()} -

    diff --git a/src/lib/components/ui/card/card-footer.svelte b/src/lib/components/ui/card/card-footer.svelte deleted file mode 100644 index 00b5850e..00000000 --- a/src/lib/components/ui/card/card-footer.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - -
    - {@render children?.()} -
    diff --git a/src/lib/components/ui/card/card-header.svelte b/src/lib/components/ui/card/card-header.svelte deleted file mode 100644 index 15d2c952..00000000 --- a/src/lib/components/ui/card/card-header.svelte +++ /dev/null @@ -1,23 +0,0 @@ - - -
    - {@render children?.()} -
    diff --git a/src/lib/components/ui/card/card-title.svelte b/src/lib/components/ui/card/card-title.svelte deleted file mode 100644 index f3b2a4e4..00000000 --- a/src/lib/components/ui/card/card-title.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - -
    - {@render children?.()} -
    diff --git a/src/lib/components/ui/card/card.svelte b/src/lib/components/ui/card/card.svelte deleted file mode 100644 index 0bf33eec..00000000 --- a/src/lib/components/ui/card/card.svelte +++ /dev/null @@ -1,22 +0,0 @@ - - -
    img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl group/card flex flex-col", className)} - {...restProps} -> - {@render children?.()} -
    diff --git a/src/lib/components/ui/card/index.ts b/src/lib/components/ui/card/index.ts deleted file mode 100644 index 4d3fce48..00000000 --- a/src/lib/components/ui/card/index.ts +++ /dev/null @@ -1,25 +0,0 @@ -import Root from "./card.svelte"; -import Content from "./card-content.svelte"; -import Description from "./card-description.svelte"; -import Footer from "./card-footer.svelte"; -import Header from "./card-header.svelte"; -import Title from "./card-title.svelte"; -import Action from "./card-action.svelte"; - -export { - Root, - Content, - Description, - Footer, - Header, - Title, - Action, - // - Root as Card, - Content as CardContent, - Description as CardDescription, - Footer as CardFooter, - Header as CardHeader, - Title as CardTitle, - Action as CardAction, -}; diff --git a/src/lib/components/ui/checkbox/checkbox.svelte b/src/lib/components/ui/checkbox/checkbox.svelte deleted file mode 100644 index 234154d0..00000000 --- a/src/lib/components/ui/checkbox/checkbox.svelte +++ /dev/null @@ -1,39 +0,0 @@ - - - - {#snippet children({ checked, indeterminate })} -
    - {#if checked} - - {:else if indeterminate} - - {/if} -
    - {/snippet} -
    diff --git a/src/lib/components/ui/checkbox/index.ts b/src/lib/components/ui/checkbox/index.ts deleted file mode 100644 index 6d92d945..00000000 --- a/src/lib/components/ui/checkbox/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -import Root from "./checkbox.svelte"; -export { - Root, - // - Root as Checkbox, -}; diff --git a/src/lib/components/ui/collapsible/collapsible-content.svelte b/src/lib/components/ui/collapsible/collapsible-content.svelte deleted file mode 100644 index bdabb559..00000000 --- a/src/lib/components/ui/collapsible/collapsible-content.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/src/lib/components/ui/collapsible/collapsible-trigger.svelte b/src/lib/components/ui/collapsible/collapsible-trigger.svelte deleted file mode 100644 index ece7ad68..00000000 --- a/src/lib/components/ui/collapsible/collapsible-trigger.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/src/lib/components/ui/collapsible/collapsible.svelte b/src/lib/components/ui/collapsible/collapsible.svelte deleted file mode 100644 index 39cdd4e4..00000000 --- a/src/lib/components/ui/collapsible/collapsible.svelte +++ /dev/null @@ -1,11 +0,0 @@ - - - diff --git a/src/lib/components/ui/collapsible/index.ts b/src/lib/components/ui/collapsible/index.ts deleted file mode 100644 index 169b4791..00000000 --- a/src/lib/components/ui/collapsible/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -import Root from "./collapsible.svelte"; -import Trigger from "./collapsible-trigger.svelte"; -import Content from "./collapsible-content.svelte"; - -export { - Root, - Content, - Trigger, - // - Root as Collapsible, - Content as CollapsibleContent, - Trigger as CollapsibleTrigger, -}; diff --git a/src/lib/components/ui/command/command-dialog.svelte b/src/lib/components/ui/command/command-dialog.svelte deleted file mode 100644 index ce6c1e03..00000000 --- a/src/lib/components/ui/command/command-dialog.svelte +++ /dev/null @@ -1,42 +0,0 @@ - - - - - {title} - {description} - - - - - diff --git a/src/lib/components/ui/command/command-empty.svelte b/src/lib/components/ui/command/command-empty.svelte deleted file mode 100644 index 1afcf7c2..00000000 --- a/src/lib/components/ui/command/command-empty.svelte +++ /dev/null @@ -1,17 +0,0 @@ - - - diff --git a/src/lib/components/ui/command/command-group.svelte b/src/lib/components/ui/command/command-group.svelte deleted file mode 100644 index 74c948af..00000000 --- a/src/lib/components/ui/command/command-group.svelte +++ /dev/null @@ -1,32 +0,0 @@ - - - - {#if heading} - - {heading} - - {/if} - - diff --git a/src/lib/components/ui/command/command-input.svelte b/src/lib/components/ui/command/command-input.svelte deleted file mode 100644 index 0dda6bf8..00000000 --- a/src/lib/components/ui/command/command-input.svelte +++ /dev/null @@ -1,34 +0,0 @@ - - -
    - - - {#snippet child({ props })} - - {/snippet} - - - - - -
    diff --git a/src/lib/components/ui/command/command-item.svelte b/src/lib/components/ui/command/command-item.svelte deleted file mode 100644 index 22930ed7..00000000 --- a/src/lib/components/ui/command/command-item.svelte +++ /dev/null @@ -1,25 +0,0 @@ - - - - {@render children?.()} - - diff --git a/src/lib/components/ui/command/command-link-item.svelte b/src/lib/components/ui/command/command-link-item.svelte deleted file mode 100644 index ab8cd707..00000000 --- a/src/lib/components/ui/command/command-link-item.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - - diff --git a/src/lib/components/ui/command/command-list.svelte b/src/lib/components/ui/command/command-list.svelte deleted file mode 100644 index f3016d44..00000000 --- a/src/lib/components/ui/command/command-list.svelte +++ /dev/null @@ -1,17 +0,0 @@ - - - diff --git a/src/lib/components/ui/command/command-loading.svelte b/src/lib/components/ui/command/command-loading.svelte deleted file mode 100644 index 19dd2985..00000000 --- a/src/lib/components/ui/command/command-loading.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/src/lib/components/ui/command/command-separator.svelte b/src/lib/components/ui/command/command-separator.svelte deleted file mode 100644 index 767fb56a..00000000 --- a/src/lib/components/ui/command/command-separator.svelte +++ /dev/null @@ -1,17 +0,0 @@ - - - diff --git a/src/lib/components/ui/command/command-shortcut.svelte b/src/lib/components/ui/command/command-shortcut.svelte deleted file mode 100644 index 19fc358e..00000000 --- a/src/lib/components/ui/command/command-shortcut.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - - - {@render children?.()} - diff --git a/src/lib/components/ui/command/command.svelte b/src/lib/components/ui/command/command.svelte deleted file mode 100644 index b87561e9..00000000 --- a/src/lib/components/ui/command/command.svelte +++ /dev/null @@ -1,25 +0,0 @@ - - - diff --git a/src/lib/components/ui/command/index.ts b/src/lib/components/ui/command/index.ts deleted file mode 100644 index 5435fbe8..00000000 --- a/src/lib/components/ui/command/index.ts +++ /dev/null @@ -1,37 +0,0 @@ -import Root from "./command.svelte"; -import Loading from "./command-loading.svelte"; -import Dialog from "./command-dialog.svelte"; -import Empty from "./command-empty.svelte"; -import Group from "./command-group.svelte"; -import Item from "./command-item.svelte"; -import Input from "./command-input.svelte"; -import List from "./command-list.svelte"; -import Separator from "./command-separator.svelte"; -import Shortcut from "./command-shortcut.svelte"; -import LinkItem from "./command-link-item.svelte"; - -export { - Root, - Dialog, - Empty, - Group, - Item, - LinkItem, - Input, - List, - Separator, - Shortcut, - Loading, - // - Root as Command, - Dialog as CommandDialog, - Empty as CommandEmpty, - Group as CommandGroup, - Item as CommandItem, - LinkItem as CommandLinkItem, - Input as CommandInput, - List as CommandList, - Separator as CommandSeparator, - Shortcut as CommandShortcut, - Loading as CommandLoading, -}; diff --git a/src/lib/components/ui/data-table/data-table.svelte.ts b/src/lib/components/ui/data-table/data-table.svelte.ts deleted file mode 100644 index f3c30a7f..00000000 --- a/src/lib/components/ui/data-table/data-table.svelte.ts +++ /dev/null @@ -1,142 +0,0 @@ -import { - type RowData, - type TableOptions, - type TableOptionsResolved, - type TableState, - type Updater, - createTable, -} from "@tanstack/table-core"; - -/** - * Creates a reactive TanStack table object for Svelte. - * @param options Table options to create the table with. - * @returns A reactive table object. - * @example - * ```svelte - * - * - * - * - * {#each table.getHeaderGroups() as headerGroup} - * - * {#each headerGroup.headers as header} - * - * {/each} - * - * {/each} - * - * - *
    - * - *
    - * ``` - */ -export function createSvelteTable(options: TableOptions) { - const resolvedOptions: TableOptionsResolved = mergeObjects( - { - state: {}, - onStateChange() {}, - renderFallbackValue: null, - mergeOptions: ( - defaultOptions: TableOptions, - options: Partial> - ) => { - return mergeObjects(defaultOptions, options); - }, - }, - options - ); - - const table = createTable(resolvedOptions); - let state = $state(table.initialState); - - function updateOptions() { - table.setOptions(() => { - return mergeObjects(resolvedOptions, options, { - state: mergeObjects(state, options.state || {}), - - onStateChange: (updater: Updater) => { - if (updater instanceof Function) state = updater(state); - else state = mergeObjects(state, updater); - - options.onStateChange?.(updater); - }, - }); - }); - } - - updateOptions(); - - $effect.pre(() => { - updateOptions(); - }); - - return table; -} - -type MaybeThunk = T | (() => T | null | undefined); -type Intersection = (T extends [infer H, ...infer R] - ? H & Intersection - : unknown) & {}; - -/** - * Lazily merges several objects (or thunks) while preserving - * getter semantics from every source. - * - * Proxy-based to avoid known WebKit recursion issue. - */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export function mergeObjects[]>( - ...sources: Sources -): Intersection<{ [K in keyof Sources]: Sources[K] }> { - const resolve = (src: MaybeThunk): T | undefined => - typeof src === "function" ? (src() ?? undefined) : src; - - const findSourceWithKey = (key: PropertyKey) => { - for (let i = sources.length - 1; i >= 0; i--) { - const obj = resolve(sources[i]); - if (obj && key in obj) return obj; - } - return undefined; - }; - - return new Proxy(Object.create(null), { - get(_, key) { - const src = findSourceWithKey(key); - - return src?.[key as never]; - }, - - has(_, key) { - return !!findSourceWithKey(key); - }, - - ownKeys(): (string | symbol)[] { - // eslint-disable-next-line svelte/prefer-svelte-reactivity - const all = new Set(); - for (const s of sources) { - const obj = resolve(s); - if (obj) { - for (const k of Reflect.ownKeys(obj) as (string | symbol)[]) { - all.add(k); - } - } - } - return [...all]; - }, - - getOwnPropertyDescriptor(_, key) { - const src = findSourceWithKey(key); - if (!src) return undefined; - return { - configurable: true, - enumerable: true, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - value: (src as any)[key], - writable: true, - }; - }, - }) as Intersection<{ [K in keyof Sources]: Sources[K] }>; -} diff --git a/src/lib/components/ui/data-table/flex-render.svelte b/src/lib/components/ui/data-table/flex-render.svelte deleted file mode 100644 index ac82a581..00000000 --- a/src/lib/components/ui/data-table/flex-render.svelte +++ /dev/null @@ -1,40 +0,0 @@ - - -{#if typeof content === "string"} - {content} -{:else if content instanceof Function} - - - {@const result = content(context as any)} - {#if result instanceof RenderComponentConfig} - {@const { component: Component, props } = result} - - {:else if result instanceof RenderSnippetConfig} - {@const { snippet, params } = result} - {@render snippet({ ...params, attach })} - {:else} - {result} - {/if} -{/if} diff --git a/src/lib/components/ui/data-table/index.ts b/src/lib/components/ui/data-table/index.ts deleted file mode 100644 index 5f4e77ea..00000000 --- a/src/lib/components/ui/data-table/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { default as FlexRender } from "./flex-render.svelte"; -export { renderComponent, renderSnippet } from "./render-helpers.js"; -export { createSvelteTable } from "./data-table.svelte.js"; diff --git a/src/lib/components/ui/data-table/render-helpers.ts b/src/lib/components/ui/data-table/render-helpers.ts deleted file mode 100644 index fa036d62..00000000 --- a/src/lib/components/ui/data-table/render-helpers.ts +++ /dev/null @@ -1,111 +0,0 @@ -import type { Component, ComponentProps, Snippet } from "svelte"; - -/** - * A helper class to make it easy to identify Svelte components in - * `columnDef.cell` and `columnDef.header` properties. - * - * > NOTE: This class should only be used internally by the adapter. If you're - * reading this and you don't know what this is for, you probably don't need it. - * - * @example - * ```svelte - * {@const result = content(context as any)} - * {#if result instanceof RenderComponentConfig} - * {@const { component: Component, props } = result} - * - * {/if} - * ``` - */ -export class RenderComponentConfig { - component: TComponent; - props: ComponentProps | Record; - constructor( - component: TComponent, - props: ComponentProps | Record = {} - ) { - this.component = component; - this.props = props; - } -} - -/** - * A helper class to make it easy to identify Svelte Snippets in `columnDef.cell` and `columnDef.header` properties. - * - * > NOTE: This class should only be used internally by the adapter. If you're - * reading this and you don't know what this is for, you probably don't need it. - * - * @example - * ```svelte - * {@const result = content(context as any)} - * {#if result instanceof RenderSnippetConfig} - * {@const { snippet, params } = result} - * {@render snippet(params)} - * {/if} - * ``` - */ -export class RenderSnippetConfig { - snippet: Snippet<[TProps]>; - params: TProps; - constructor(snippet: Snippet<[TProps]>, params: TProps) { - this.snippet = snippet; - this.params = params; - } -} - -/** - * A helper function to help create cells from Svelte components through ColumnDef's `cell` and `header` properties. - * - * This is only to be used with Svelte Components - use `renderSnippet` for Svelte Snippets. - * - * @param component A Svelte component - * @param props The props to pass to `component` - * @returns A `RenderComponentConfig` object that helps svelte-table know how to render the header/cell component. - * @example - * ```ts - * // +page.svelte - * const defaultColumns = [ - * columnHelper.accessor('name', { - * header: header => renderComponent(SortHeader, { label: 'Name', header }), - * }), - * columnHelper.accessor('state', { - * header: header => renderComponent(SortHeader, { label: 'State', header }), - * }), - * ] - * ``` - * @see {@link https://tanstack.com/table/latest/docs/guide/column-defs} - */ -export function renderComponent< - // eslint-disable-next-line @typescript-eslint/no-explicit-any - T extends Component, - Props extends ComponentProps, ->(component: T, props: Props = {} as Props) { - return new RenderComponentConfig(component, props); -} - -/** - * A helper function to help create cells from Svelte Snippets through ColumnDef's `cell` and `header` properties. - * - * The snippet must only take one parameter. - * - * This is only to be used with Snippets - use `renderComponent` for Svelte Components. - * - * @param snippet - * @param params - * @returns - A `RenderSnippetConfig` object that helps svelte-table know how to render the header/cell snippet. - * @example - * ```ts - * // +page.svelte - * const defaultColumns = [ - * columnHelper.accessor('name', { - * cell: cell => renderSnippet(nameSnippet, { name: cell.row.name }), - * }), - * columnHelper.accessor('state', { - * cell: cell => renderSnippet(stateSnippet, { state: cell.row.state }), - * }), - * ] - * ``` - * @see {@link https://tanstack.com/table/latest/docs/guide/column-defs} - */ -export function renderSnippet(snippet: Snippet<[TProps]>, params: TProps = {} as TProps) { - return new RenderSnippetConfig(snippet, params); -} diff --git a/src/lib/components/ui/dialog/dialog-close.svelte b/src/lib/components/ui/dialog/dialog-close.svelte deleted file mode 100644 index de68f2f0..00000000 --- a/src/lib/components/ui/dialog/dialog-close.svelte +++ /dev/null @@ -1,11 +0,0 @@ - - - diff --git a/src/lib/components/ui/dialog/dialog-content.svelte b/src/lib/components/ui/dialog/dialog-content.svelte deleted file mode 100644 index 42bb07c5..00000000 --- a/src/lib/components/ui/dialog/dialog-content.svelte +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - {@render children?.()} - {#if showCloseButton} - - {#snippet child({ props })} - - {/snippet} - - {/if} - - diff --git a/src/lib/components/ui/dialog/dialog-description.svelte b/src/lib/components/ui/dialog/dialog-description.svelte deleted file mode 100644 index e8197975..00000000 --- a/src/lib/components/ui/dialog/dialog-description.svelte +++ /dev/null @@ -1,17 +0,0 @@ - - - diff --git a/src/lib/components/ui/dialog/dialog-footer.svelte b/src/lib/components/ui/dialog/dialog-footer.svelte deleted file mode 100644 index 1714a809..00000000 --- a/src/lib/components/ui/dialog/dialog-footer.svelte +++ /dev/null @@ -1,32 +0,0 @@ - - -
    - {@render children?.()} - {#if showCloseButton} - - {#snippet child({ props })} - - {/snippet} - - {/if} -
    diff --git a/src/lib/components/ui/dialog/dialog-header.svelte b/src/lib/components/ui/dialog/dialog-header.svelte deleted file mode 100644 index 1c8f0ba9..00000000 --- a/src/lib/components/ui/dialog/dialog-header.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - -
    - {@render children?.()} -
    diff --git a/src/lib/components/ui/dialog/dialog-overlay.svelte b/src/lib/components/ui/dialog/dialog-overlay.svelte deleted file mode 100644 index e3ad3be3..00000000 --- a/src/lib/components/ui/dialog/dialog-overlay.svelte +++ /dev/null @@ -1,17 +0,0 @@ - - - diff --git a/src/lib/components/ui/dialog/dialog-portal.svelte b/src/lib/components/ui/dialog/dialog-portal.svelte deleted file mode 100644 index ccfa79ca..00000000 --- a/src/lib/components/ui/dialog/dialog-portal.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/src/lib/components/ui/dialog/dialog-title.svelte b/src/lib/components/ui/dialog/dialog-title.svelte deleted file mode 100644 index 4d769a43..00000000 --- a/src/lib/components/ui/dialog/dialog-title.svelte +++ /dev/null @@ -1,17 +0,0 @@ - - - diff --git a/src/lib/components/ui/dialog/dialog-trigger.svelte b/src/lib/components/ui/dialog/dialog-trigger.svelte deleted file mode 100644 index 589ee0c3..00000000 --- a/src/lib/components/ui/dialog/dialog-trigger.svelte +++ /dev/null @@ -1,11 +0,0 @@ - - - diff --git a/src/lib/components/ui/dialog/dialog.svelte b/src/lib/components/ui/dialog/dialog.svelte deleted file mode 100644 index 211672c6..00000000 --- a/src/lib/components/ui/dialog/dialog.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/src/lib/components/ui/dialog/index.ts b/src/lib/components/ui/dialog/index.ts deleted file mode 100644 index 076cef52..00000000 --- a/src/lib/components/ui/dialog/index.ts +++ /dev/null @@ -1,34 +0,0 @@ -import Root from "./dialog.svelte"; -import Portal from "./dialog-portal.svelte"; -import Title from "./dialog-title.svelte"; -import Footer from "./dialog-footer.svelte"; -import Header from "./dialog-header.svelte"; -import Overlay from "./dialog-overlay.svelte"; -import Content from "./dialog-content.svelte"; -import Description from "./dialog-description.svelte"; -import Trigger from "./dialog-trigger.svelte"; -import Close from "./dialog-close.svelte"; - -export { - Root, - Title, - Portal, - Footer, - Header, - Trigger, - Overlay, - Content, - Description, - Close, - // - Root as Dialog, - Title as DialogTitle, - Portal as DialogPortal, - Footer as DialogFooter, - Header as DialogHeader, - Trigger as DialogTrigger, - Overlay as DialogOverlay, - Content as DialogContent, - Description as DialogDescription, - Close as DialogClose, -}; diff --git a/src/lib/components/ui/drawer/drawer-close.svelte b/src/lib/components/ui/drawer/drawer-close.svelte deleted file mode 100644 index 95c24796..00000000 --- a/src/lib/components/ui/drawer/drawer-close.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/src/lib/components/ui/drawer/drawer-content.svelte b/src/lib/components/ui/drawer/drawer-content.svelte deleted file mode 100644 index ff1f5349..00000000 --- a/src/lib/components/ui/drawer/drawer-content.svelte +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - {@render children?.()} - - diff --git a/src/lib/components/ui/drawer/drawer-description.svelte b/src/lib/components/ui/drawer/drawer-description.svelte deleted file mode 100644 index ea0cbe9b..00000000 --- a/src/lib/components/ui/drawer/drawer-description.svelte +++ /dev/null @@ -1,17 +0,0 @@ - - - diff --git a/src/lib/components/ui/drawer/drawer-footer.svelte b/src/lib/components/ui/drawer/drawer-footer.svelte deleted file mode 100644 index 48479704..00000000 --- a/src/lib/components/ui/drawer/drawer-footer.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - -
    - {@render children?.()} -
    diff --git a/src/lib/components/ui/drawer/drawer-header.svelte b/src/lib/components/ui/drawer/drawer-header.svelte deleted file mode 100644 index da89cb0a..00000000 --- a/src/lib/components/ui/drawer/drawer-header.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - -
    - {@render children?.()} -
    diff --git a/src/lib/components/ui/drawer/drawer-nested.svelte b/src/lib/components/ui/drawer/drawer-nested.svelte deleted file mode 100644 index 834af946..00000000 --- a/src/lib/components/ui/drawer/drawer-nested.svelte +++ /dev/null @@ -1,12 +0,0 @@ - - - diff --git a/src/lib/components/ui/drawer/drawer-overlay.svelte b/src/lib/components/ui/drawer/drawer-overlay.svelte deleted file mode 100644 index 14c73c84..00000000 --- a/src/lib/components/ui/drawer/drawer-overlay.svelte +++ /dev/null @@ -1,17 +0,0 @@ - - - diff --git a/src/lib/components/ui/drawer/drawer-portal.svelte b/src/lib/components/ui/drawer/drawer-portal.svelte deleted file mode 100644 index 5a0dd740..00000000 --- a/src/lib/components/ui/drawer/drawer-portal.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/src/lib/components/ui/drawer/drawer-title.svelte b/src/lib/components/ui/drawer/drawer-title.svelte deleted file mode 100644 index b7891ea7..00000000 --- a/src/lib/components/ui/drawer/drawer-title.svelte +++ /dev/null @@ -1,17 +0,0 @@ - - - diff --git a/src/lib/components/ui/drawer/drawer-trigger.svelte b/src/lib/components/ui/drawer/drawer-trigger.svelte deleted file mode 100644 index f1877d8e..00000000 --- a/src/lib/components/ui/drawer/drawer-trigger.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/src/lib/components/ui/drawer/drawer.svelte b/src/lib/components/ui/drawer/drawer.svelte deleted file mode 100644 index 0cb57ff9..00000000 --- a/src/lib/components/ui/drawer/drawer.svelte +++ /dev/null @@ -1,12 +0,0 @@ - - - diff --git a/src/lib/components/ui/drawer/index.ts b/src/lib/components/ui/drawer/index.ts deleted file mode 100644 index 1656cac5..00000000 --- a/src/lib/components/ui/drawer/index.ts +++ /dev/null @@ -1,38 +0,0 @@ -import Root from "./drawer.svelte"; -import Content from "./drawer-content.svelte"; -import Description from "./drawer-description.svelte"; -import Overlay from "./drawer-overlay.svelte"; -import Footer from "./drawer-footer.svelte"; -import Header from "./drawer-header.svelte"; -import Title from "./drawer-title.svelte"; -import NestedRoot from "./drawer-nested.svelte"; -import Close from "./drawer-close.svelte"; -import Trigger from "./drawer-trigger.svelte"; -import Portal from "./drawer-portal.svelte"; - -export { - Root, - NestedRoot, - Content, - Description, - Overlay, - Footer, - Header, - Title, - Trigger, - Portal, - Close, - - // - Root as Drawer, - NestedRoot as DrawerNestedRoot, - Content as DrawerContent, - Description as DrawerDescription, - Overlay as DrawerOverlay, - Footer as DrawerFooter, - Header as DrawerHeader, - Title as DrawerTitle, - Trigger as DrawerTrigger, - Portal as DrawerPortal, - Close as DrawerClose, -}; diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte deleted file mode 100644 index e0e19718..00000000 --- a/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte +++ /dev/null @@ -1,16 +0,0 @@ - - - diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte deleted file mode 100644 index d9d9db5d..00000000 --- a/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte +++ /dev/null @@ -1,44 +0,0 @@ - - - - {#snippet children({ checked, indeterminate })} - - {#if indeterminate} - - {:else if checked} - - {/if} - - {@render childrenProp?.()} - {/snippet} - diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-content.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-content.svelte deleted file mode 100644 index ee83a9bf..00000000 --- a/src/lib/components/ui/dropdown-menu/dropdown-menu-content.svelte +++ /dev/null @@ -1,31 +0,0 @@ - - - - - diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte deleted file mode 100644 index 9532da06..00000000 --- a/src/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte +++ /dev/null @@ -1,22 +0,0 @@ - - - diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-group.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-group.svelte deleted file mode 100644 index aca1f7bd..00000000 --- a/src/lib/components/ui/dropdown-menu/dropdown-menu-group.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-item.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-item.svelte deleted file mode 100644 index 58349d3e..00000000 --- a/src/lib/components/ui/dropdown-menu/dropdown-menu-item.svelte +++ /dev/null @@ -1,27 +0,0 @@ - - - diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-label.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-label.svelte deleted file mode 100644 index 31e06a21..00000000 --- a/src/lib/components/ui/dropdown-menu/dropdown-menu-label.svelte +++ /dev/null @@ -1,24 +0,0 @@ - - -
    - {@render children?.()} -
    diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-portal.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-portal.svelte deleted file mode 100644 index 274cfef7..00000000 --- a/src/lib/components/ui/dropdown-menu/dropdown-menu-portal.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte deleted file mode 100644 index 189aef40..00000000 --- a/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte +++ /dev/null @@ -1,16 +0,0 @@ - - - diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte deleted file mode 100644 index 05e0d532..00000000 --- a/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte +++ /dev/null @@ -1,34 +0,0 @@ - - - - {#snippet children({ checked })} - - {#if checked} - - {/if} - - {@render childrenProp?.({ checked })} - {/snippet} - diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-separator.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-separator.svelte deleted file mode 100644 index db1f0135..00000000 --- a/src/lib/components/ui/dropdown-menu/dropdown-menu-separator.svelte +++ /dev/null @@ -1,17 +0,0 @@ - - - diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte deleted file mode 100644 index 98bb6113..00000000 --- a/src/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - - - {@render children?.()} - diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte deleted file mode 100644 index 5a6c135f..00000000 --- a/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte +++ /dev/null @@ -1,17 +0,0 @@ - - - diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte deleted file mode 100644 index 024bbc8f..00000000 --- a/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte +++ /dev/null @@ -1,29 +0,0 @@ - - - - {@render children?.()} - - diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-sub.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-sub.svelte deleted file mode 100644 index f0445813..00000000 --- a/src/lib/components/ui/dropdown-menu/dropdown-menu-sub.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-trigger.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-trigger.svelte deleted file mode 100644 index cb053444..00000000 --- a/src/lib/components/ui/dropdown-menu/dropdown-menu-trigger.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu.svelte deleted file mode 100644 index cb4bc621..00000000 --- a/src/lib/components/ui/dropdown-menu/dropdown-menu.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/src/lib/components/ui/dropdown-menu/index.ts b/src/lib/components/ui/dropdown-menu/index.ts deleted file mode 100644 index 7850c6a3..00000000 --- a/src/lib/components/ui/dropdown-menu/index.ts +++ /dev/null @@ -1,54 +0,0 @@ -import Root from "./dropdown-menu.svelte"; -import Sub from "./dropdown-menu-sub.svelte"; -import CheckboxGroup from "./dropdown-menu-checkbox-group.svelte"; -import CheckboxItem from "./dropdown-menu-checkbox-item.svelte"; -import Content from "./dropdown-menu-content.svelte"; -import Group from "./dropdown-menu-group.svelte"; -import Item from "./dropdown-menu-item.svelte"; -import Label from "./dropdown-menu-label.svelte"; -import RadioGroup from "./dropdown-menu-radio-group.svelte"; -import RadioItem from "./dropdown-menu-radio-item.svelte"; -import Separator from "./dropdown-menu-separator.svelte"; -import Shortcut from "./dropdown-menu-shortcut.svelte"; -import Trigger from "./dropdown-menu-trigger.svelte"; -import SubContent from "./dropdown-menu-sub-content.svelte"; -import SubTrigger from "./dropdown-menu-sub-trigger.svelte"; -import GroupHeading from "./dropdown-menu-group-heading.svelte"; -import Portal from "./dropdown-menu-portal.svelte"; - -export { - CheckboxGroup, - CheckboxItem, - Content, - Portal, - Root as DropdownMenu, - CheckboxGroup as DropdownMenuCheckboxGroup, - CheckboxItem as DropdownMenuCheckboxItem, - Content as DropdownMenuContent, - Portal as DropdownMenuPortal, - Group as DropdownMenuGroup, - Item as DropdownMenuItem, - Label as DropdownMenuLabel, - RadioGroup as DropdownMenuRadioGroup, - RadioItem as DropdownMenuRadioItem, - Separator as DropdownMenuSeparator, - Shortcut as DropdownMenuShortcut, - Sub as DropdownMenuSub, - SubContent as DropdownMenuSubContent, - SubTrigger as DropdownMenuSubTrigger, - Trigger as DropdownMenuTrigger, - GroupHeading as DropdownMenuGroupHeading, - Group, - GroupHeading, - Item, - Label, - RadioGroup, - RadioItem, - Root, - Separator, - Shortcut, - Sub, - SubContent, - SubTrigger, - Trigger, -}; diff --git a/src/lib/components/ui/empty/empty-content.svelte b/src/lib/components/ui/empty/empty-content.svelte deleted file mode 100644 index 520ac878..00000000 --- a/src/lib/components/ui/empty/empty-content.svelte +++ /dev/null @@ -1,23 +0,0 @@ - - -
    - {@render children?.()} -
    diff --git a/src/lib/components/ui/empty/empty-description.svelte b/src/lib/components/ui/empty/empty-description.svelte deleted file mode 100644 index e6d97cde..00000000 --- a/src/lib/components/ui/empty/empty-description.svelte +++ /dev/null @@ -1,23 +0,0 @@ - - -
    a:hover]:text-primary text-sm/relaxed [&>a]:underline [&>a]:underline-offset-4", - className - )} - {...restProps} -> - {@render children?.()} -
    diff --git a/src/lib/components/ui/empty/empty-header.svelte b/src/lib/components/ui/empty/empty-header.svelte deleted file mode 100644 index 9085f955..00000000 --- a/src/lib/components/ui/empty/empty-header.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - -
    - {@render children?.()} -
    diff --git a/src/lib/components/ui/empty/empty-media.svelte b/src/lib/components/ui/empty/empty-media.svelte deleted file mode 100644 index 6bc65c0f..00000000 --- a/src/lib/components/ui/empty/empty-media.svelte +++ /dev/null @@ -1,41 +0,0 @@ - - - - -
    - {@render children?.()} -
    diff --git a/src/lib/components/ui/empty/empty-title.svelte b/src/lib/components/ui/empty/empty-title.svelte deleted file mode 100644 index 3641794b..00000000 --- a/src/lib/components/ui/empty/empty-title.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - -
    - {@render children?.()} -
    diff --git a/src/lib/components/ui/empty/empty.svelte b/src/lib/components/ui/empty/empty.svelte deleted file mode 100644 index e5f37460..00000000 --- a/src/lib/components/ui/empty/empty.svelte +++ /dev/null @@ -1,23 +0,0 @@ - - -
    - {@render children?.()} -
    diff --git a/src/lib/components/ui/empty/index.ts b/src/lib/components/ui/empty/index.ts deleted file mode 100644 index ae4c106e..00000000 --- a/src/lib/components/ui/empty/index.ts +++ /dev/null @@ -1,22 +0,0 @@ -import Root from "./empty.svelte"; -import Header from "./empty-header.svelte"; -import Media from "./empty-media.svelte"; -import Title from "./empty-title.svelte"; -import Description from "./empty-description.svelte"; -import Content from "./empty-content.svelte"; - -export { - Root, - Header, - Media, - Title, - Description, - Content, - // - Root as Empty, - Header as EmptyHeader, - Media as EmptyMedia, - Title as EmptyTitle, - Description as EmptyDescription, - Content as EmptyContent, -}; diff --git a/src/lib/components/ui/field/field-content.svelte b/src/lib/components/ui/field/field-content.svelte deleted file mode 100644 index 694a885b..00000000 --- a/src/lib/components/ui/field/field-content.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - -
    - {@render children?.()} -
    diff --git a/src/lib/components/ui/field/field-description.svelte b/src/lib/components/ui/field/field-description.svelte deleted file mode 100644 index 9580b775..00000000 --- a/src/lib/components/ui/field/field-description.svelte +++ /dev/null @@ -1,25 +0,0 @@ - - -

    a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4", - className - )} - {...restProps} -> - {@render children?.()} -

    diff --git a/src/lib/components/ui/field/field-error.svelte b/src/lib/components/ui/field/field-error.svelte deleted file mode 100644 index 7abff78c..00000000 --- a/src/lib/components/ui/field/field-error.svelte +++ /dev/null @@ -1,58 +0,0 @@ - - -{#if hasContent} - -{/if} diff --git a/src/lib/components/ui/field/field-group.svelte b/src/lib/components/ui/field/field-group.svelte deleted file mode 100644 index eaf9a1c8..00000000 --- a/src/lib/components/ui/field/field-group.svelte +++ /dev/null @@ -1,23 +0,0 @@ - - -
    - {@render children?.()} -
    diff --git a/src/lib/components/ui/field/field-label.svelte b/src/lib/components/ui/field/field-label.svelte deleted file mode 100644 index 533866b8..00000000 --- a/src/lib/components/ui/field/field-label.svelte +++ /dev/null @@ -1,25 +0,0 @@ - - - diff --git a/src/lib/components/ui/field/field-legend.svelte b/src/lib/components/ui/field/field-legend.svelte deleted file mode 100644 index ec601fdb..00000000 --- a/src/lib/components/ui/field/field-legend.svelte +++ /dev/null @@ -1,24 +0,0 @@ - - - - {@render children?.()} - diff --git a/src/lib/components/ui/field/field-separator.svelte b/src/lib/components/ui/field/field-separator.svelte deleted file mode 100644 index b4c4537d..00000000 --- a/src/lib/components/ui/field/field-separator.svelte +++ /dev/null @@ -1,35 +0,0 @@ - - -
    - - {#if children} - - {@render children()} - - {/if} -
    diff --git a/src/lib/components/ui/field/field-set.svelte b/src/lib/components/ui/field/field-set.svelte deleted file mode 100644 index 7c621818..00000000 --- a/src/lib/components/ui/field/field-set.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - -
    [data-slot=checkbox-group]]:gap-3 has-[>[data-slot=radio-group]]:gap-3 flex flex-col", className)} - {...restProps} -> - {@render children?.()} -
    diff --git a/src/lib/components/ui/field/field-title.svelte b/src/lib/components/ui/field/field-title.svelte deleted file mode 100644 index 3c52cf09..00000000 --- a/src/lib/components/ui/field/field-title.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - -
    - {@render children?.()} -
    diff --git a/src/lib/components/ui/field/field.svelte b/src/lib/components/ui/field/field.svelte deleted file mode 100644 index 0c28dbd6..00000000 --- a/src/lib/components/ui/field/field.svelte +++ /dev/null @@ -1,47 +0,0 @@ - - - - -
    - {@render children?.()} -
    diff --git a/src/lib/components/ui/field/index.ts b/src/lib/components/ui/field/index.ts deleted file mode 100644 index a644a956..00000000 --- a/src/lib/components/ui/field/index.ts +++ /dev/null @@ -1,33 +0,0 @@ -import Field from "./field.svelte"; -import Set from "./field-set.svelte"; -import Legend from "./field-legend.svelte"; -import Group from "./field-group.svelte"; -import Content from "./field-content.svelte"; -import Label from "./field-label.svelte"; -import Title from "./field-title.svelte"; -import Description from "./field-description.svelte"; -import Separator from "./field-separator.svelte"; -import Error from "./field-error.svelte"; - -export { - Field, - Set, - Legend, - Group, - Content, - Label, - Title, - Description, - Separator, - Error, - // - Set as FieldSet, - Legend as FieldLegend, - Group as FieldGroup, - Content as FieldContent, - Label as FieldLabel, - Title as FieldTitle, - Description as FieldDescription, - Separator as FieldSeparator, - Error as FieldError, -}; diff --git a/src/lib/components/ui/form/form-button.svelte b/src/lib/components/ui/form/form-button.svelte deleted file mode 100644 index 48d39369..00000000 --- a/src/lib/components/ui/form/form-button.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/src/lib/components/ui/input-group/input-group-input.svelte b/src/lib/components/ui/input-group/input-group-input.svelte deleted file mode 100644 index 6e8a63e5..00000000 --- a/src/lib/components/ui/input-group/input-group-input.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - - diff --git a/src/lib/components/ui/input-group/input-group-text.svelte b/src/lib/components/ui/input-group/input-group-text.svelte deleted file mode 100644 index 98e00d58..00000000 --- a/src/lib/components/ui/input-group/input-group-text.svelte +++ /dev/null @@ -1,19 +0,0 @@ - - - - {@render children?.()} - diff --git a/src/lib/components/ui/input-group/input-group-textarea.svelte b/src/lib/components/ui/input-group/input-group-textarea.svelte deleted file mode 100644 index 9f8c53e7..00000000 --- a/src/lib/components/ui/input-group/input-group-textarea.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - - diff --git a/src/lib/components/ui/toggle-group/index.ts b/src/lib/components/ui/toggle-group/index.ts deleted file mode 100644 index 12b14b96..00000000 --- a/src/lib/components/ui/toggle-group/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -import Root from "./toggle-group.svelte"; -import Item from "./toggle-group-item.svelte"; - -export { - Root, - Item, - // - Root as ToggleGroup, - Item as ToggleGroupItem, -}; diff --git a/src/lib/components/ui/toggle-group/toggle-group-item.svelte b/src/lib/components/ui/toggle-group/toggle-group-item.svelte deleted file mode 100644 index 263ed688..00000000 --- a/src/lib/components/ui/toggle-group/toggle-group-item.svelte +++ /dev/null @@ -1,35 +0,0 @@ - - - diff --git a/src/lib/components/ui/toggle-group/toggle-group.svelte b/src/lib/components/ui/toggle-group/toggle-group.svelte deleted file mode 100644 index be614494..00000000 --- a/src/lib/components/ui/toggle-group/toggle-group.svelte +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - diff --git a/src/lib/components/ui/toggle/index.ts b/src/lib/components/ui/toggle/index.ts deleted file mode 100644 index 8cb2936f..00000000 --- a/src/lib/components/ui/toggle/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -import Root from "./toggle.svelte"; -export { - toggleVariants, - type ToggleSize, - type ToggleVariant, - type ToggleVariants, -} from "./toggle.svelte"; - -export { - Root, - // - Root as Toggle, -}; diff --git a/src/lib/components/ui/toggle/toggle.svelte b/src/lib/components/ui/toggle/toggle.svelte deleted file mode 100644 index 44fc7059..00000000 --- a/src/lib/components/ui/toggle/toggle.svelte +++ /dev/null @@ -1,51 +0,0 @@ - - - - - diff --git a/src/lib/components/ui/tooltip/index.ts b/src/lib/components/ui/tooltip/index.ts deleted file mode 100644 index 17186042..00000000 --- a/src/lib/components/ui/tooltip/index.ts +++ /dev/null @@ -1,19 +0,0 @@ -import Root from "./tooltip.svelte"; -import Trigger from "./tooltip-trigger.svelte"; -import Content from "./tooltip-content.svelte"; -import Provider from "./tooltip-provider.svelte"; -import Portal from "./tooltip-portal.svelte"; - -export { - Root, - Trigger, - Content, - Provider, - Portal, - // - Root as Tooltip, - Content as TooltipContent, - Trigger as TooltipTrigger, - Provider as TooltipProvider, - Portal as TooltipPortal, -}; diff --git a/src/lib/components/ui/tooltip/tooltip-content.svelte b/src/lib/components/ui/tooltip/tooltip-content.svelte deleted file mode 100644 index 993742e9..00000000 --- a/src/lib/components/ui/tooltip/tooltip-content.svelte +++ /dev/null @@ -1,52 +0,0 @@ - - - - - {@render children?.()} - - {#snippet child({ props })} -
    - {/snippet} -
    -
    -
    diff --git a/src/lib/components/ui/tooltip/tooltip-portal.svelte b/src/lib/components/ui/tooltip/tooltip-portal.svelte deleted file mode 100644 index d234f7d7..00000000 --- a/src/lib/components/ui/tooltip/tooltip-portal.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/src/lib/components/ui/tooltip/tooltip-provider.svelte b/src/lib/components/ui/tooltip/tooltip-provider.svelte deleted file mode 100644 index 6dba9a67..00000000 --- a/src/lib/components/ui/tooltip/tooltip-provider.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/src/lib/components/ui/tooltip/tooltip-trigger.svelte b/src/lib/components/ui/tooltip/tooltip-trigger.svelte deleted file mode 100644 index c4b21fc7..00000000 --- a/src/lib/components/ui/tooltip/tooltip-trigger.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/src/lib/components/ui/tooltip/tooltip.svelte b/src/lib/components/ui/tooltip/tooltip.svelte deleted file mode 100644 index 03c9a3d9..00000000 --- a/src/lib/components/ui/tooltip/tooltip.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/src/lib/components/utils/MultiPauseToggle.svelte b/src/lib/components/utils/MultiPauseToggle.svelte index 4ef40694..b578cb07 100644 --- a/src/lib/components/utils/MultiPauseToggle.svelte +++ b/src/lib/components/utils/MultiPauseToggle.svelte @@ -2,8 +2,8 @@ import { shockerPauseShocker, shockerShockerShareCodePause } from '$lib/api'; import type { BooleanLegacyDataResponse } from '$lib/api'; import { Asterisk, Pause, Play } from '@lucide/svelte'; - import { Button } from '$lib/components/ui/button'; - import { Spinner } from '$lib/components/ui/spinner'; + import { Button } from '$hadcn/button'; + import { Spinner } from '$hadcn/spinner'; import { handleApiError } from '$lib/errorhandling/apiErrorHandling'; interface Props { diff --git a/src/lib/components/utils/PauseToggle.svelte b/src/lib/components/utils/PauseToggle.svelte index 19415d30..8a544570 100644 --- a/src/lib/components/utils/PauseToggle.svelte +++ b/src/lib/components/utils/PauseToggle.svelte @@ -2,8 +2,8 @@ import { shockerPauseShocker, shockerShockerShareCodePause } from '$lib/api'; import type { BooleanLegacyDataResponse } from '$lib/api'; import { Pause, Play } from '@lucide/svelte'; - import { Button } from '$lib/components/ui/button'; - import { Spinner } from '$lib/components/ui/spinner'; + import { Button } from '$hadcn/button'; + import { Spinner } from '$hadcn/spinner'; import { handleApiError } from '$lib/errorhandling/apiErrorHandling'; interface Props { diff --git a/src/lib/errorhandling/ProblemDetails.ts b/src/lib/errorhandling/ProblemDetails.ts index 11d19c0d..9aa412c7 100644 --- a/src/lib/errorhandling/ProblemDetails.ts +++ b/src/lib/errorhandling/ProblemDetails.ts @@ -1,5 +1,4 @@ -import { isObject, isString } from '$lib/typeguards'; -import { HasNumber, HasString } from '$lib/typeguards/propGuards'; +import { HasNumber, HasString, isObject, isString } from '$core/typeguards'; export interface ProblemDetails { type: string; diff --git a/src/lib/errorhandling/ValidationProblemDetails.ts b/src/lib/errorhandling/ValidationProblemDetails.ts index 37b1b38f..4c7dd80a 100644 --- a/src/lib/errorhandling/ValidationProblemDetails.ts +++ b/src/lib/errorhandling/ValidationProblemDetails.ts @@ -1,5 +1,5 @@ -import { isObject } from '$lib/typeguards'; -import type { ValidationResult } from '$lib/types/ValidationResult'; +import { isObject } from '$core/typeguards'; +import type { ValidationResult } from '$core/types/ValidationResult'; import type { ProblemDetails } from './ProblemDetails'; export interface ValidationProblemDetails extends ProblemDetails { diff --git a/src/lib/hooks/is-mobile.svelte.ts b/src/lib/hooks/is-mobile.svelte.ts deleted file mode 100644 index e3802d38..00000000 --- a/src/lib/hooks/is-mobile.svelte.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { MediaQuery } from 'svelte/reactivity'; - -const DEFAULT_MOBILE_BREAKPOINT = 768; - -export class IsMobile extends MediaQuery { - constructor(breakpoint: number = DEFAULT_MOBILE_BREAKPOINT) { - super(`max-width: ${breakpoint - 1}px`); - } -} diff --git a/src/lib/inputvalidation/emailValidator.test.ts b/src/lib/inputvalidation/emailValidator.test.ts deleted file mode 100644 index f5c9ba16..00000000 --- a/src/lib/inputvalidation/emailValidator.test.ts +++ /dev/null @@ -1,200 +0,0 @@ -import { describe, expect, it } from 'vitest'; -import { isEmailAddress, validateEmail } from './emailValidator'; - -describe('isEmailAddress', () => { - it('returns false for empty string', () => { - expect(isEmailAddress('')).toBe(false); - }); - - it('returns false when missing "@" or has multiple "@"', () => { - expect(isEmailAddress('plainaddress')).toBe(false); - expect(isEmailAddress('a@b@c.com')).toBe(false); - }); - - it('returns false when total length exceeds 320 characters', () => { - const localPart = 'a'.repeat(64); - const domainLabel = 'b'.repeat(63); - const domain = Array(5).fill(domainLabel).join('.'); // 5×63 + 4 dots = 319 - const validEmail = `${localPart}@${domain}`; // 384 chars total - expect(validEmail.length).toBe(64 + 1 + 319); - expect(isEmailAddress(validEmail)).toBe(false); - }); - - it('returns false when local part exceeds 64 characters', () => { - const account = 'x'.repeat(65); - const address = 'domain.com'; - expect(isEmailAddress(`${account}@${address}`)).toBe(false); - }); - - it('returns false when domain part exceeds 255 characters', () => { - const account = 'user'; - const longLabel = 'd'.repeat(63); - // 4 labels of 63 chars + 3 dots = 4*63 + 3 = 255 - const domain = Array(4).fill(longLabel).join('.'); - expect(domain.length).toBe(255); - // Prepend one character to push domain over 255 - const tooLongDomain = 'e' + domain; - expect(isEmailAddress(`${account}@${tooLongDomain}`)).toBe(false); - }); - - it('returns false when any domain label exceeds 63 characters', () => { - const account = 'user'; - const longLabel = 'd'.repeat(64); - const address = `${longLabel}.com`; - expect(isEmailAddress(`${account}@${address}`)).toBe(false); - }); - - it('returns false for invalid characters or formats not matching regex', () => { - // starts with a dot - expect(isEmailAddress('.user@domain.com')).toBe(false); - // consecutive dots in local part - expect(isEmailAddress('user..name@domain.com')).toBe(false); - // hyphen at start of domain label - expect(isEmailAddress('user@-domain.com')).toBe(false); - // no TLD - expect(isEmailAddress('user@domain')).toBe(false); - }); - - it('returns true for valid standard email addresses', () => { - expect(isEmailAddress('simple@example.com')).toBe(true); - expect(isEmailAddress('very.common@example.co.uk')).toBe(true); - expect(isEmailAddress("o'reilly@example.io")).toBe(true); - expect(isEmailAddress('user_name-123@sub.domain.com')).toBe(true); - }); -}); - -describe('validateEmail', () => { - it('returns null for empty input', () => { - const result = validateEmail(''); - expect(result).toBeNull(); - }); - - it('returns valid: false and message "Invalid email" for syntactically invalid addresses', () => { - const invalids = [ - 'noatsign.com', - 'user@.com', - 'user@domain..com', - 'user@domain', - 'toolong' + 'a'.repeat(320) + '@example.com', - ]; - for (const addr of invalids) { - const result = validateEmail(addr); - expect(result).not.toBeNull(); - expect(result?.valid).toBe(false); - expect(result?.message).toBe('Invalid email'); - } - }); - - it('returns valid: false and message "Email cannot contain aliases" when email contains "+"', () => { - const withAlias = 'user+alias@example.com'; - const result = validateEmail(withAlias); - expect(result).not.toBeNull(); - expect(result?.valid).toBe(false); - expect(result?.message).toBe('Email cannot contain aliases'); - }); - - it('returns valid: true for valid email without "+"', () => { - const valid = 'firstname.lastname@domain.com'; - const result = validateEmail(valid); - expect(result).not.toBeNull(); - expect(result?.valid).toBe(true); - expect(result).not.toHaveProperty('message'); - }); - - it('treats "+" anywhere in the local part as invalid alias', () => { - const examples = [ - 'plus+sign@domain.com', - '+start@domain.com', - 'end+@domain.com', - 'middle+more@sub.domain.org', - ]; - for (const addr of examples) { - const result = validateEmail(addr); - expect(result).not.toBeNull(); - expect(result?.valid).toBe(false); - expect(result?.message).toBe('Email cannot contain aliases'); - } - }); - - it('does not reject valid emails with hyphens in domain or underscores in local part', () => { - const examples = [ - 'user_name@example-domain.com', // underscore in local, hyphen in domain - 'another.user-name@sub.domain.com', // hyphen in both portions - ]; - for (const addr of examples) { - const result = validateEmail(addr); - expect(result).not.toBeNull(); - expect(result?.valid).toBe(true); - } - }); -}); - -describe('isEmailAddress boundary cases', () => { - it('accepts a 320-char address at the upper boundary', () => { - // 4 × 63-char alpha labels + 3 dots = 255-char domain (max). - // 64-char local + '@' + 255-char domain = 320 (max total). - const local = 'b'.repeat(64); - const label = 'a'.repeat(63); - const domain = [label, label, label, label].join('.'); - const addr = `${local}@${domain}`; - expect(domain.length).toBe(255); - expect(addr.length).toBe(320); - expect(isEmailAddress(addr)).toBe(true); - }); - - it('returns false for empty local part', () => { - expect(isEmailAddress('@example.com')).toBe(false); - }); - - it('returns false for empty domain part', () => { - expect(isEmailAddress('user@')).toBe(false); - }); - - it('returns false for "@" only', () => { - expect(isEmailAddress('@')).toBe(false); - }); - - it('returns false for trailing whitespace (regex anchors enforce this)', () => { - expect(isEmailAddress('user@example.com ')).toBe(false); - expect(isEmailAddress(' user@example.com')).toBe(false); - }); - - it('returns false when domain TLD is numeric', () => { - expect(isEmailAddress('user@example.123')).toBe(false); - }); - - it('returns false for a hyphen at the start of any domain label', () => { - expect(isEmailAddress('user@sub.-example.com')).toBe(false); - }); - - it('returns true at the exact local-part length of 64', () => { - const local = 'a'.repeat(64); - expect(isEmailAddress(`${local}@example.com`)).toBe(true); - }); -}); - -describe('validateEmail boundary cases', () => { - it('rejects "+" at the very start of local part as alias', () => { - const result = validateEmail('+plus@example.com'); - expect(result?.valid).toBe(false); - expect(result?.message).toBe('Email cannot contain aliases'); - }); - - it('rejects "+" at the end of local part as alias', () => { - const result = validateEmail('plus+@example.com'); - expect(result?.valid).toBe(false); - expect(result?.message).toBe('Email cannot contain aliases'); - }); - - it('rejects multiple "+" signs as alias', () => { - const result = validateEmail('a+b+c@example.com'); - expect(result?.valid).toBe(false); - expect(result?.message).toBe('Email cannot contain aliases'); - }); - - it('treats whitespace-only input as empty (returns null)', () => { - // value.length is 0 only for ''; non-empty whitespace falls through to invalid - expect(validateEmail('')).toBeNull(); - expect(validateEmail(' ')?.valid).toBe(false); - }); -}); diff --git a/src/lib/inputvalidation/emailValidator.ts b/src/lib/inputvalidation/emailValidator.ts deleted file mode 100644 index deebd9ec..00000000 --- a/src/lib/inputvalidation/emailValidator.ts +++ /dev/null @@ -1,46 +0,0 @@ -import type { ValidationResult } from '$lib/types/ValidationResult'; - -const emailRegex = - /^[\w-!#$%&'*+/=?^`{|}~](\.?[\w-!#$%&'*+/=?^`{|}~])*@[a-zA-Z0-9](-*\.?[a-zA-Z0-9])*\.[a-zA-Z](-?[a-zA-Z0-9])+$/; - -export function isEmailAddress(value: string): boolean { - if (!value) return false; - if (value.length > 320) return false; - - const emailParts = value.split('@'); - - if (emailParts.length !== 2) return false; - - const [account, address] = emailParts; - - if (account.length > 64) return false; - if (address.length > 255) return false; - - const domainParts = address.split('.'); - - if (domainParts.some((part) => part.length > 63)) return false; - - return emailRegex.test(value); -} - -export function validateEmail(value: string): ValidationResult | null { - if (value.length == 0) { - return null; - } - - if (!isEmailAddress(value)) { - return { - valid: false, - message: 'Invalid email', - }; - } - - if (value.includes('+')) { - return { - valid: false, - message: 'Email cannot contain aliases', - }; - } - - return { valid: true }; -} diff --git a/src/lib/inputvalidation/passwordValidator.test.ts b/src/lib/inputvalidation/passwordValidator.test.ts deleted file mode 100644 index fe7126ac..00000000 --- a/src/lib/inputvalidation/passwordValidator.test.ts +++ /dev/null @@ -1,182 +0,0 @@ -import { describe, expect, it } from 'vitest'; -import { getPasswordStrength, validatePassword, validatePasswordMatch } from './passwordValidator'; - -describe('validatePassword', () => { - it('returns null for empty password', () => { - const result = validatePassword(''); - expect(result).toBeNull(); - }); - - it('rejects passwords shorter than 12 characters', () => { - const result = validatePassword('shortPwd1!'); - expect(result).not.toBeNull(); - expect(result?.valid).toBe(false); - expect(result?.message).toBe('Password is too short'); - }); - - it('rejects passwords longer than 256 characters', () => { - const longPwd = 'a'.repeat(257); - const result = validatePassword(longPwd); - expect(result).not.toBeNull(); - expect(result?.valid).toBe(false); - expect(result?.message).toBe(`Seriously? ${longPwd.length} characters? That's too much`); - }); - - it('rejects passwords consisting only of whitespaces', () => { - const spaces = ' \r \n \t \r \n '; - const result = validatePassword(spaces); - expect(result).not.toBeNull(); - expect(result?.valid).toBe(false); - expect(result?.message).toBe('Password cannot consist of only whitespaces'); - }); - - it('rejects passwords that start or end with whitespace', () => { - const leading = ' validPassword123'; - const trailing = 'validPassword123 '; - const both = ' validPassword123 '; - for (const pwd of [leading, trailing, both]) { - const result = validatePassword(pwd); - expect(result).not.toBeNull(); - expect(result?.valid).toBe(false); - expect(result?.message).toBe('Password cannot start or end with whitespace'); - } - }); - - it('accepts valid passwords of acceptable length and no leading/trailing whitespace', () => { - const valid = 'ValidPassword123'; - const result = validatePassword(valid); - expect(result).not.toBeNull(); - expect(result?.valid).toBe(true); - expect(result).not.toHaveProperty('message'); - }); -}); - -describe('validatePasswordMatch', () => { - it('returns null when original password is empty', () => { - const result = validatePasswordMatch('', 'anything'); - expect(result).toBeNull(); - }); - - it('rejects non-matching passwords', () => { - const result = validatePasswordMatch('password123', 'password124'); - expect(result).not.toBeNull(); - expect(result?.valid).toBe(false); - expect(result?.message).toBe('Passwords do not match'); - }); - - it('accepts matching passwords', () => { - const result = validatePasswordMatch('password123', 'password123'); - expect(result).not.toBeNull(); - expect(result?.valid).toBe(true); - expect(result).not.toHaveProperty('message'); - }); - - it('rejects empty confirmation against non-empty password', () => { - const result = validatePasswordMatch('password123', ''); - expect(result?.valid).toBe(false); - expect(result?.message).toBe('Passwords do not match'); - }); - - it('treats unicode-equivalent strings as a literal mismatch (no NFC normalization)', () => { - // Composed "é" vs decomposed "e" + combining acute - const composed = 'pässword1234'; - const decomposed = 'pässword1234'; // combining diaeresis - expect(composed).not.toEqual(decomposed); - const result = validatePasswordMatch(composed, decomposed); - expect(result?.valid).toBe(false); - }); -}); - -describe('validatePassword boundary cases', () => { - it('accepts exactly 12 characters (lower boundary)', () => { - const pwd = 'a'.repeat(12); - const result = validatePassword(pwd); - expect(result?.valid).toBe(true); - }); - - it('rejects exactly 11 characters (just below)', () => { - const result = validatePassword('a'.repeat(11)); - expect(result?.valid).toBe(false); - expect(result?.message).toBe('Password is too short'); - }); - - it('accepts exactly 256 characters (upper boundary)', () => { - const result = validatePassword('a'.repeat(256)); - expect(result?.valid).toBe(true); - }); - - it('rejects exactly 257 characters (just above)', () => { - const result = validatePassword('a'.repeat(257)); - expect(result?.valid).toBe(false); - expect(result?.message).toMatch(/Seriously\?/); - }); - - it('accepts internal whitespace within otherwise valid password', () => { - const result = validatePassword('a strong pass!'); - expect(result?.valid).toBe(true); - }); - - it('rejects tab-only passwords as whitespace-only', () => { - const result = validatePassword('\t'.repeat(12)); - expect(result?.valid).toBe(false); - expect(result?.message).toBe('Password cannot consist of only whitespaces'); - }); -}); - -describe('getPasswordStrength', () => { - it('returns None/gray/0% for empty string', () => { - const { percent, text, color } = getPasswordStrength(''); - expect(percent).toBe(0); - expect(text).toBe('None'); - expect(color).toBe('gray'); - }); - - it('rates a repeated single-character password as Very weak (red)', () => { - // "aaaaaaaaaaaa" (12×'a'): uniqueLength=1 ⇒ entropy=0 ⇒ percent=0 ⇒ <30 - const pwd = 'a'.repeat(12); - const { percent, text, color } = getPasswordStrength(pwd); - expect(percent).toBe(0); - expect(text).toBe('Very weak'); - expect(color).toBe('red'); - }); - - it('rates a moderately varied 12-character password as Weak (orange)', () => { - // "abcABC123!@#": length=12, uniqueLength=12 ⇒ entropy≈43 ⇒ percent≈35.8 ⇒ <50 - const pwd = 'abcABC123!@#'; - const { percent, text, color } = getPasswordStrength(pwd); - expect(percent).toBeGreaterThanOrEqual(30); - expect(percent).toBeLessThan(50); - expect(text).toBe('Weak'); - expect(color).toBe('orange'); - }); - - it('rates a 60-character password with two unique chars as Fair (yellow)', () => { - // 60×(two-character alphabet) ⇒ entropy=60*1=60 ⇒ percent=50 ⇒ <60 - const pwd = 'ab'.repeat(30); - const { percent, text, color } = getPasswordStrength(pwd); - expect(percent).toBeCloseTo(50, 1); - expect(text).toBe('Fair'); - expect(color).toBe('yellow'); - }); - - it('rates a 72-character password with two unique chars as Strong (green)', () => { - // 72×(two-character alphabet) ⇒ entropy=72 ⇒ percent=60 ⇒ <99 - const pwd = 'ab'.repeat(36); - const { percent, text, color } = getPasswordStrength(pwd); - expect(percent).toBeCloseTo(60, 1); - expect(text).toBe('Strong'); - expect(color).toBe('green'); - }); - - it('caps strength at 100% and rates as Very strong (cyan) for high entropy', () => { - // 100 random characters - const randomBytes = new Uint8Array(100); - crypto.getRandomValues(randomBytes); - const pwd = Array.from(randomBytes, (b) => String.fromCharCode((b % 94) + 33)).join(''); - - const { percent, text, color } = getPasswordStrength(pwd); - expect(percent).toBe(100); - expect(text).toBe('Very strong'); - expect(color).toBe('cyan'); - }); -}); diff --git a/src/lib/inputvalidation/passwordValidator.ts b/src/lib/inputvalidation/passwordValidator.ts deleted file mode 100644 index 9040d449..00000000 --- a/src/lib/inputvalidation/passwordValidator.ts +++ /dev/null @@ -1,92 +0,0 @@ -import type { TwTextColor } from '$lib/types/Tailwind'; -import type { ValidationResult } from '$lib/types/ValidationResult'; -import { calculateStringEntropy } from '$lib/utils/entropy'; - -export function validatePassword(value: string): ValidationResult | null { - if (value.length == 0) { - return null; - } - - const result = { - valid: false, - message: '', - }; - - if (value.length < 12) { - result.message = 'Password is too short'; - return result; - } - - if (value.length > 256) { - result.message = `Seriously? ${value.length} characters? That's too much`; - return result; - } - - const trimmedLength = value.trim().length; - if (trimmedLength == 0) { - result.message = 'Password cannot consist of only whitespaces'; - return result; - } - - if (trimmedLength != value.length) { - result.message = 'Password cannot start or end with whitespace'; - return result; - } - - return { valid: true }; -} - -export function validatePasswordMatch( - password: string, - passwordConfirmation: string -): ValidationResult | null { - if (password.length == 0) { - return null; - } - - if (password != passwordConfirmation) { - return { - valid: false, - message: 'Passwords do not match', - }; - } - - return { valid: true }; -} - -export function getPasswordStrength(value: string): { - percent: number; - text: string; - color: TwTextColor; -} { - let percent: number; - let text: string; - let color: TwTextColor; - - if (value.length === 0) { - percent = 0; - text = 'None'; - color = 'gray'; - } else { - percent = Math.min((calculateStringEntropy(value) / 120) * 100, 100); - - if (percent < 30) { - text = 'Very weak'; - color = 'red'; - } else if (percent < 50) { - text = 'Weak'; - color = 'orange'; - } else if (percent < 60) { - text = 'Fair'; - color = 'yellow'; - } else if (percent < 99) { - text = 'Strong'; - color = 'green'; - } else { - text = 'Very strong'; - color = 'cyan'; - } - } - - return { percent, text, color }; -} diff --git a/src/lib/inputvalidation/usernameValidator.ts b/src/lib/inputvalidation/usernameValidator.ts index 3dd4ed1a..bbc06c7f 100644 --- a/src/lib/inputvalidation/usernameValidator.ts +++ b/src/lib/inputvalidation/usernameValidator.ts @@ -1,7 +1,7 @@ +import { isEmailAddress } from '$core/inputvalidation/emailValidator'; +import type { ValidationResult } from '$core/types/ValidationResult'; import type { UsernameCheckResponse } from '$lib/api'; import { UsernameAvailability } from '$lib/api'; -import { isEmailAddress } from '$lib/inputvalidation/emailValidator'; -import type { ValidationResult } from '$lib/types/ValidationResult'; const MultipleWhiteSpaceRegex = /\s{2,}/; diff --git a/src/lib/signalr/handlers/DeviceUpdate.ts b/src/lib/signalr/handlers/DeviceUpdate.ts index 51a87648..dcc6ab30 100644 --- a/src/lib/signalr/handlers/DeviceUpdate.ts +++ b/src/lib/signalr/handlers/DeviceUpdate.ts @@ -1,6 +1,6 @@ +import { isString } from '$core/typeguards'; import { isHubUpdateType } from '$lib/signalr/models/HubUpdateType'; import { refreshOwnHubs } from '$lib/state/hubs-state.svelte'; -import { isString } from '$lib/typeguards'; import { toast } from 'svelte-sonner'; export function handleSignalrDeviceUpdate(deviceId: unknown, updateType: unknown) { diff --git a/src/lib/signalr/handlers/OtaInstallFailed.ts b/src/lib/signalr/handlers/OtaInstallFailed.ts index eda2fcc8..57b4fda3 100644 --- a/src/lib/signalr/handlers/OtaInstallFailed.ts +++ b/src/lib/signalr/handlers/OtaInstallFailed.ts @@ -1,5 +1,5 @@ +import { isBoolean, isNumber, isString } from '$core/typeguards'; import { onlineHubs } from '$lib/state/hubs-state.svelte'; -import { isBoolean, isNumber, isString } from '$lib/typeguards'; import { toast } from 'svelte-sonner'; /** diff --git a/src/lib/signalr/handlers/OtaInstallProgress.ts b/src/lib/signalr/handlers/OtaInstallProgress.ts index f1dbac7e..1a09988e 100644 --- a/src/lib/signalr/handlers/OtaInstallProgress.ts +++ b/src/lib/signalr/handlers/OtaInstallProgress.ts @@ -1,6 +1,6 @@ +import { isNumber, isString } from '$core/typeguards'; import { isOtaUpdateProgressTask } from '$lib/signalr/models/OtaUpdateProgressTask'; import { onlineHubs } from '$lib/state/hubs-state.svelte'; -import { isNumber, isString } from '$lib/typeguards'; import { toast } from 'svelte-sonner'; /** diff --git a/src/lib/signalr/handlers/OtaInstallStarted.ts b/src/lib/signalr/handlers/OtaInstallStarted.ts index 3a7d72b0..6060164a 100644 --- a/src/lib/signalr/handlers/OtaInstallStarted.ts +++ b/src/lib/signalr/handlers/OtaInstallStarted.ts @@ -1,5 +1,5 @@ +import { isNumber, isString } from '$core/typeguards'; import { onlineHubs } from '$lib/state/hubs-state.svelte'; -import { isNumber, isString } from '$lib/typeguards'; import { toast } from 'svelte-sonner'; /** diff --git a/src/lib/signalr/handlers/OtaInstallSucceeded.ts b/src/lib/signalr/handlers/OtaInstallSucceeded.ts index 81cb1e2e..9276edd5 100644 --- a/src/lib/signalr/handlers/OtaInstallSucceeded.ts +++ b/src/lib/signalr/handlers/OtaInstallSucceeded.ts @@ -1,5 +1,5 @@ +import { isNumber, isString } from '$core/typeguards'; import { onlineHubs } from '$lib/state/hubs-state.svelte'; -import { isNumber, isString } from '$lib/typeguards'; import { toast } from 'svelte-sonner'; /** diff --git a/src/lib/signalr/handlers/OtaRollback.ts b/src/lib/signalr/handlers/OtaRollback.ts index de678c79..95c6b588 100644 --- a/src/lib/signalr/handlers/OtaRollback.ts +++ b/src/lib/signalr/handlers/OtaRollback.ts @@ -1,5 +1,5 @@ +import { isNumber, isString } from '$core/typeguards'; import { onlineHubs } from '$lib/state/hubs-state.svelte'; -import { isNumber, isString } from '$lib/typeguards'; import { toast } from 'svelte-sonner'; /** diff --git a/src/lib/signalr/models/ControlLog.ts b/src/lib/signalr/models/ControlLog.ts index 71cd7a84..cf519a7b 100644 --- a/src/lib/signalr/models/ControlLog.ts +++ b/src/lib/signalr/models/ControlLog.ts @@ -1,5 +1,4 @@ -import { isObject } from '$lib/typeguards'; -import { HasNumber, HasString } from '$lib/typeguards/propGuards'; +import { HasNumber, HasString, isObject } from '$core/typeguards'; import { ControlType, isControlType } from './ControlType'; interface ControlLogShockerInfo { diff --git a/src/lib/signalr/models/ControlLogSender.ts b/src/lib/signalr/models/ControlLogSender.ts index 105f9fd2..3966027b 100644 --- a/src/lib/signalr/models/ControlLogSender.ts +++ b/src/lib/signalr/models/ControlLogSender.ts @@ -1,5 +1,4 @@ -import { isObject } from '$lib/typeguards'; -import { HasObject, HasString, HasStringOrNull } from '$lib/typeguards/propGuards'; +import { HasObject, HasString, HasStringOrNull, isObject } from '$core/typeguards'; export interface ControlLogSender { connectionId: string; diff --git a/src/lib/signalr/models/ControlType.ts b/src/lib/signalr/models/ControlType.ts index d6c5aa7b..e8bf21a3 100644 --- a/src/lib/signalr/models/ControlType.ts +++ b/src/lib/signalr/models/ControlType.ts @@ -1,4 +1,4 @@ -import { isNumber } from '$lib/typeguards'; +import { isNumber } from '$core/typeguards'; export enum ControlType { Stop = 0, diff --git a/src/lib/signalr/models/DeviceOnlineState.ts b/src/lib/signalr/models/DeviceOnlineState.ts index 0cb5915e..a9560341 100644 --- a/src/lib/signalr/models/DeviceOnlineState.ts +++ b/src/lib/signalr/models/DeviceOnlineState.ts @@ -1,5 +1,4 @@ -import { isObject } from '$lib/typeguards'; -import { HasBoolean, HasString, HasStringOrNull } from '$lib/typeguards/propGuards'; +import { HasBoolean, HasString, HasStringOrNull, isObject } from '$core/typeguards'; export interface DeviceOnlineState { device: string; diff --git a/src/lib/signalr/models/HubUpdateType.ts b/src/lib/signalr/models/HubUpdateType.ts index 92d2eb63..07100880 100644 --- a/src/lib/signalr/models/HubUpdateType.ts +++ b/src/lib/signalr/models/HubUpdateType.ts @@ -1,4 +1,4 @@ -import { isNumber } from '$lib/typeguards'; +import { isNumber } from '$core/typeguards'; export enum HubUpdateType { HubCreated = 0, diff --git a/src/lib/signalr/models/OtaUpdateProgressTask.ts b/src/lib/signalr/models/OtaUpdateProgressTask.ts index bf528193..5834642c 100644 --- a/src/lib/signalr/models/OtaUpdateProgressTask.ts +++ b/src/lib/signalr/models/OtaUpdateProgressTask.ts @@ -1,4 +1,4 @@ -import { isNumber } from '$lib/typeguards'; +import { isNumber } from '$core/typeguards'; export enum OtaUpdateProgressTask { FetchingMetadata = 0, diff --git a/src/lib/state/auth-state.svelte.ts b/src/lib/state/auth-state.svelte.ts index 061f6944..7e34230d 100644 --- a/src/lib/state/auth-state.svelte.ts +++ b/src/lib/state/auth-state.svelte.ts @@ -1,4 +1,4 @@ -import { dialog } from '$lib/components/dialog-manager/dialog-store.svelte'; +import { dialog } from '$core/components/dialog-manager/dialog-store.svelte'; import { registerOnUnauthorized } from '$lib/errorhandling/apiErrorHandling'; import { destroySignalR, initializeSignalR } from '$lib/signalr/user.svelte'; import { diff --git a/src/lib/state/color-scheme-state.svelte.ts b/src/lib/state/color-scheme-state.svelte.ts index 73e67f33..f29ff064 100644 --- a/src/lib/state/color-scheme-state.svelte.ts +++ b/src/lib/state/color-scheme-state.svelte.ts @@ -1,4 +1,4 @@ -import { isString } from '$lib/typeguards'; +import { isString } from '$core/typeguards'; import { PersistedState } from './classes/persisted-state.svelte'; export enum ColorScheme { diff --git a/src/lib/telemetry/common.ts b/src/lib/telemetry/common.ts index 2f08cf4b..d85f17b9 100644 --- a/src/lib/telemetry/common.ts +++ b/src/lib/telemetry/common.ts @@ -1,4 +1,5 @@ import { version } from '$app/environment'; +import { isTruthy } from '$core/utils/parse'; import { PUBLIC_BACKEND_API_URL, PUBLIC_SIGNOZ_DEPLOYMENT_ENVIRONMENT, @@ -8,7 +9,6 @@ import { PUBLIC_SIGNOZ_TRACES_URL, } from '$env/static/public'; import { telemetryConsent, type TelemetryLevel } from '$lib/state/telemetry-consent-state.svelte'; -import { isTruthy } from '$lib/utils/parse'; import { resourceFromAttributes } from '@opentelemetry/resources'; export const SERVICE_NAME = 'openshock-frontend'; diff --git a/src/lib/telemetry/tracer.ts b/src/lib/telemetry/tracer.ts index 50cb1cc3..030366c1 100644 --- a/src/lib/telemetry/tracer.ts +++ b/src/lib/telemetry/tracer.ts @@ -1,5 +1,5 @@ +import { isTruthy } from '$core/utils/parse'; import { PUBLIC_SIGNOZ_TRACE_PROPAGATION } from '$env/static/public'; -import { isTruthy } from '$lib/utils/parse'; import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'; import { registerInstrumentations } from '@opentelemetry/instrumentation'; import { FetchInstrumentation } from '@opentelemetry/instrumentation-fetch'; diff --git a/src/lib/tour/onboarding-state.ts b/src/lib/tour/onboarding-state.ts index 0c56510a..fe719c05 100644 --- a/src/lib/tour/onboarding-state.ts +++ b/src/lib/tour/onboarding-state.ts @@ -1,5 +1,5 @@ +import { isTruthy } from '$core/utils/parse'; import { PUBLIC_DISABLE_ONBOARDING } from '$env/static/public'; -import { isTruthy } from '$lib/utils/parse'; export const WELCOME_COOKIE_NAME = 'os.welcomed'; // Pre-cookie builds stored "welcome seen" under this localStorage key. Kept only diff --git a/src/lib/typeguards/basicGuards.ts b/src/lib/typeguards/basicGuards.ts deleted file mode 100644 index 6baa9c21..00000000 --- a/src/lib/typeguards/basicGuards.ts +++ /dev/null @@ -1,18 +0,0 @@ -export function isObject(value: unknown): value is Record { - return typeof value === 'object' && !Array.isArray(value) && value !== null; -} -export function isString(value: unknown): value is string { - return typeof value === 'string' || value instanceof String; -} -export function isNumber(value: unknown): value is number { - return typeof value === 'number' && isFinite(value); -} -export function isBoolean(value: unknown): value is boolean { - return typeof value === 'boolean'; -} -export function isArrayBuffer(value: unknown): value is ArrayBuffer { - return value instanceof ArrayBuffer; -} -export function isStringOrNull(value: unknown): value is string | null { - return isString(value) || value === null; -} diff --git a/src/lib/typeguards/index.ts b/src/lib/typeguards/index.ts deleted file mode 100644 index e5d287ec..00000000 --- a/src/lib/typeguards/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './basicGuards'; -export * from './twitterHandleGuard'; diff --git a/src/lib/typeguards/propGuards.ts b/src/lib/typeguards/propGuards.ts deleted file mode 100644 index f317c506..00000000 --- a/src/lib/typeguards/propGuards.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { isBoolean, isNumber, isObject, isString } from '$lib/typeguards'; - -export function HasString( - obj: Record, - key: K -): obj is object & Record { - return Object.hasOwn(obj, key) && isString(obj[key]); -} - -export function HasStringOrNull( - obj: Record, - key: K -): obj is object & Record { - return Object.hasOwn(obj, key) && (isString(obj[key]) || obj[key] === null); -} - -export function HasNumber( - obj: Record, - key: K -): obj is object & Record { - return Object.hasOwn(obj, key) && isNumber(obj[key]); -} - -export function HasBoolean( - obj: Record, - key: K -): obj is object & Record { - return Object.hasOwn(obj, key) && isBoolean(obj[key]); -} - -export function HasObject( - obj: Record, - key: K -): obj is object & Record> { - return Object.hasOwn(obj, key) && isObject(obj[key]); -} - -export function HasStringArray( - obj: Record, - key: K -): obj is object & Record { - return ( - Object.hasOwn(obj, key) && - Array.isArray(obj[key]) && - obj[key].every((item: unknown) => isString(item)) - ); -} diff --git a/src/lib/typeguards/twitterHandleGuard.ts b/src/lib/typeguards/twitterHandleGuard.ts deleted file mode 100644 index 9dd6c82f..00000000 --- a/src/lib/typeguards/twitterHandleGuard.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { isString } from '$lib/typeguards/basicGuards'; - -export function isTwitterHandle(value: unknown): value is string { - return isString(value) && value.startsWith('@'); -} diff --git a/src/lib/types/AnyComponent.ts b/src/lib/types/AnyComponent.ts deleted file mode 100644 index 56d6e51b..00000000 --- a/src/lib/types/AnyComponent.ts +++ /dev/null @@ -1,7 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any -- type must accept any component props/events/slots signatures */ - -import type { Component, SvelteComponent } from 'svelte'; - -export type AnyComponent = - | Component - | (new (...args: any[]) => SvelteComponent); diff --git a/src/lib/types/ChildrenFunc.ts b/src/lib/types/ChildrenFunc.ts deleted file mode 100644 index 9d9fe5b3..00000000 --- a/src/lib/types/ChildrenFunc.ts +++ /dev/null @@ -1,3 +0,0 @@ -import type { Snippet } from 'svelte'; - -export type ChildrenFunc = () => ReturnType; diff --git a/src/lib/types/Tailwind.ts b/src/lib/types/Tailwind.ts deleted file mode 100644 index 83dd200d..00000000 --- a/src/lib/types/Tailwind.ts +++ /dev/null @@ -1,11 +0,0 @@ -export const twTextColor = { - gray: 'text-gray-500', - red: 'text-red-500', - orange: 'text-orange-500', - yellow: 'text-yellow-500', - green: 'text-green-500', - cyan: 'text-cyan-500', - blue: 'text-blue-500', -} as const; - -export type TwTextColor = keyof typeof twTextColor; diff --git a/src/lib/types/ValidationResult.ts b/src/lib/types/ValidationResult.ts deleted file mode 100644 index 7221e2cc..00000000 --- a/src/lib/types/ValidationResult.ts +++ /dev/null @@ -1,13 +0,0 @@ -import type { TwTextColor } from '$lib/types/Tailwind'; - -export type ValidationResult = { - valid: boolean; - message?: string; - color?: TwTextColor; - link?: { text: string; href: string }; -}; - -export function GetValResColor(valRes: ValidationResult): TwTextColor { - if (valRes.color !== undefined) return valRes.color; - return valRes.valid ? 'green' : 'red'; -} diff --git a/src/lib/utils/clipboard.svelte.ts b/src/lib/utils/clipboard.svelte.ts deleted file mode 100644 index f12536e4..00000000 --- a/src/lib/utils/clipboard.svelte.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { onDestroy } from 'svelte'; -import { toast } from 'svelte-sonner'; - -const DEFAULT_SUCCESS_MESSAGE = 'Copied to clipboard'; -const DEFAULT_ERROR_MESSAGE = 'Failed to copy to clipboard'; - -/** - * Writes text to the clipboard and toasts the outcome. Fire-and-forget — use - * when no reactive feedback is needed. For a reactive `copied` flag, use the - * `Clipboard` class. - */ -export async function copyToClipboard( - text: string, - successMessage: string = DEFAULT_SUCCESS_MESSAGE -): Promise { - try { - await navigator.clipboard.writeText(text); - toast.success(successMessage); - return true; - } catch { - // Insecure context, permission denied, tab not focused, etc. - toast.error(DEFAULT_ERROR_MESSAGE); - return false; - } -} - -export interface ClipboardOptions { - /** How long `copied` stays true after a successful copy, in ms. Defaults to 2000. */ - resetDelay?: number; -} - -/** - * Clipboard wrapper with a reactive `copied` flag that auto-resets. Call - * `dispose()` when done (or use `useClipboard` to do that automatically). - */ -export class Clipboard { - readonly #resetDelay: number; - #timeout?: ReturnType; - #copied = $state(false); - - constructor(options: ClipboardOptions = {}) { - this.#resetDelay = options.resetDelay ?? 2000; - } - - get copied() { - return this.#copied; - } - - async copy(text: string, successMessage?: string): Promise { - const ok = await copyToClipboard(text, successMessage); - if (!ok) return false; - - this.#copied = true; - clearTimeout(this.#timeout); - this.#timeout = setTimeout(() => (this.#copied = false), this.#resetDelay); - return true; - } - - /** Clears any pending reset timeout. */ - dispose() { - clearTimeout(this.#timeout); - this.#timeout = undefined; - } -} - -/** Component-aware `Clipboard` that clears pending reset timeouts on unmount. */ -export function useClipboard(options?: ClipboardOptions): Clipboard { - const clip = new Clipboard(options); - onDestroy(() => clip.dispose()); - return clip; -} diff --git a/src/lib/utils/convert.test.ts b/src/lib/utils/convert.test.ts deleted file mode 100644 index 3916e486aad1a1f03ae06c149d5fd12cee62bffb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7115 zcmbtZU2fY(5bkqMG4Ml0)sjLI=9|B5xLPM7gU=A~bSA6hbSq5tsINLxU z#j8p8{0^M7+r2EgCDSZ9ycQ~3K$zPQHHe(|525t4+*Dvz*nu{4rIoh}9V5G%4nbCuSAxj|Q@d5!m z*)L^q>KJ=%gy3^+t+pyo5aUcR!Xyae#Q|db1qOv!vh6u6`9_=9fiw#dbiuP+#3{^k z{6kre3M?lr(H#*_A!1^|h2x|GFW~V!5i`ExadxP$PW*EOU}#xt5TG{(g89+@<0>hq zg%sbvc8*-Skb;Wy{bi$ang!y!d1Sio&oMzl=GeOgmIr{fP3GC zaW)*l3-C8{{h^TEV_&hU!A$b!!Mn?Vvaq4xRm4@yG^8c6YIjPemPyXZhz=E<1jiu7 zG#hc4yuG@)0Xp}1A_Ut~{9=a1FmpBoVn-NZx*oJEzu(E*J=&dCby6D6<( z;UcATtwn;xTGC2~g9DBUSUTTZ8PC#yD@|3;;kyc29b2R(wIV=;{9Z72AJ9>Qq2`{k zMzIn>mu8PBi?eWTPbFL3y7`6G6=sSgkAp5^yM`&x9yms}LwDK7IfgkN zA}1RFoJ^s)%jW26O1sp_Vm@}stc0`KM@OdddXaUI+_%_Of5@pXpzn#_k}Y8v&!Qa5 z2DMgBYOT3Hy_A{jh1+|3Mun!j3Y;k#bekx?)pMqj`*Lj&$eZb(QDSQcZN05e!( zM@^dcf`u$bo2xkryZHX#jK0RQHYgGspjo=(u;vgbv;iTd%Hf7*M7j9jO14$GLqSCX z2`H68tkjYu*F-&s(^SWUDi8~mbp zwPaiB#(za}UkzF*k{vq}YSjZQp4A3aSC+ay@>Eez^su$ZJo0I={H&}$I{zBmiUygE z@5!ziOLr80JjFY<->%U2Hlk3hfHuuMzcMf?Z{m3vhuD=h>n&a%tlaE4*n+Ov(PY9-0v5Xt*24e` z;8u;_-*o+gJuQa#sEBd8f+;^XJu6w#t>R9Gq^lWu5uifzk&MY;n$PE0#r54mhTfA? zfxj7}B{(?b@kgA*KJg00b#ICt?;AskM^{lM4ZmaGQnL%J%$>Xtl`G3d-cgi z&M2lQGxJK3-<#GG#>V>^M0LQ&RFUD(Ez5&fJkSV90S$>j-Vx%3A+;#dxm~%_6xc>D zBmDKYLz%1X#1*|c-c@=2=47CsDbN2O?>H(B@K33G_u|bN=FbvxZEXWkbpJqAzDr{< zF_3L5;AkaIEP54=zxS;P@;g(?4%&(J%G&$SUuFHTBm<{OJEUDQb%(Ae0uJj0>stzV zU4|EB;FZ*eZO9|M6zbGCn=P$0AxGU0`DZEX%fSOL>VF+BmX@8Al3tF7FFQc`fZ6zp$;@i5S#MYl2mM{z1t?{$-F z)f0S;*PkA3bOH)3!vi@!Z zGp#wnA}7gW7)5UA5``^Qfd6Mj`a~BZ@8X43b*fa`QFaEy6T2iRj4GjM<@!U*jTgcX za0Xb{hV6#RL*q`(7j8O`JW{4ON7mRn4;-V~yxKh%{>=?lVGBZ`=1 v3|lcA(79|>B;2yYb(~a8j7{l&a5~ZyX#x-5)=IVQkpF~~b=Ct>ASC_;jeLKc diff --git a/src/lib/utils/convert.ts b/src/lib/utils/convert.ts deleted file mode 100644 index 7ab798be..00000000 --- a/src/lib/utils/convert.ts +++ /dev/null @@ -1,22 +0,0 @@ -export const NumberToHexPadded = (num: number, pad: number) => - (num >>> 0).toString(16).padStart(pad, '0').toUpperCase(); - -// Convert a Uint8Array to a binary string (1 byte → 1 char) -export const u8arrToBinstr = (array: Uint8Array): string => { - let result = ''; - const chunkSize = 0x8000; // avoid "call stack too large" for huge arrays - for (let i = 0; i < array.length; i += chunkSize) { - const chunk = array.subarray(i, i + chunkSize); - result += String.fromCharCode(...chunk); - } - return result; -}; - -// Convert a binary string back to a Uint8Array -export const binstrToU8arr = (bstr: string): Uint8Array => { - const u8Array = new Uint8Array(bstr.length); - for (let i = 0; i < bstr.length; i++) { - u8Array[i] = bstr.charCodeAt(i); - } - return u8Array; -}; diff --git a/src/lib/utils/crypto.test.ts b/src/lib/utils/crypto.test.ts deleted file mode 100644 index e47cc098..00000000 --- a/src/lib/utils/crypto.test.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { describe, expect, it } from 'vitest'; -import { ArrayBufferToHex, HashBuffer, HashString } from './crypto'; -import { EncodeString } from './encoding'; - -describe('ArrayBufferToHex', () => { - it('converts an ArrayBuffer to a lowercase hex string', () => { - const bytes = new Uint8Array([0x00, 0x0f, 0xff]).buffer; - expect(ArrayBufferToHex(bytes)).toBe('000fff'); - }); - - it('handles an empty ArrayBuffer', () => { - const empty = new Uint8Array([]).buffer; - expect(ArrayBufferToHex(empty)).toBe(''); - }); - - it('pads single-digit hex values with a leading zero', () => { - const bytes = new Uint8Array([0x5, 0xa, 0x10]).buffer; - // 0x05 → "05", 0x0a → "0a", 0x10 → "10" - expect(ArrayBufferToHex(bytes)).toBe('050a10'); - }); -}); - -describe('HashBuffer', () => { - it('computes SHA-1 of a known UTF-8 byte sequence', async () => { - const data = new TextEncoder().encode('abc'); - const hash = await HashBuffer(data, 'SHA-1'); - // SHA-1("abc") = a9993e364706816aba3e25717850c26c9cd0d89d - expect(hash).toBe('a9993e364706816aba3e25717850c26c9cd0d89d'); - }); - - it('computes SHA-256 of the same UTF-8 byte sequence', async () => { - const data = new TextEncoder().encode('abc'); - const hash = await HashBuffer(data, 'SHA-256'); - // SHA-256("abc") = - // ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad - expect(hash).toBe('ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad'); - }); - - it('can hash arbitrary byte sequences, not only text', async () => { - const raw = new Uint8Array([0xde, 0xad, 0xbe, 0xef]); - const sha1Hash = await HashBuffer(raw, 'SHA-1'); - // Precomputed SHA-1 of [0xde,0xad,0xbe,0xef]: - // "d78f8bb992a56a597f6c7a1fb918bb78271367eb" - expect(sha1Hash).toBe('d78f8bb992a56a597f6c7a1fb918bb78271367eb'); - - const sha256Hash = await HashBuffer(raw, 'SHA-256'); - // Precomputed SHA-256 of [0xde,0xad,0xbe,0xef]: - // "5f78c33274e43fa9de5659265c1d917e25c03722dcb0b8d27db8d5feaa813953" - expect(sha256Hash).toBe('5f78c33274e43fa9de5659265c1d917e25c03722dcb0b8d27db8d5feaa813953'); - }); -}); - -describe('HashString', () => { - it('delegates to HashBuffer via EncodeString and computes SHA-1', async () => { - // Ensure EncodeString is actually converting "hello" to the correct Uint8Array - const manualBuffer = new TextEncoder().encode('hello'); - const expectedHex = await HashBuffer(manualBuffer, 'SHA-1'); - const hashFromString = await HashString('hello', 'SHA-1'); - expect(hashFromString).toBe(expectedHex); - }); - - it('computes SHA-256 for a longer phrase', async () => { - const phrase = 'The quick brown fox jumps over the lazy dog'; - // Known SHA-256 of that phrase: - // d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592 - const hash = await HashString(phrase, 'SHA-256'); - expect(hash).toBe('d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592'); - }); - - it('returns the same result as HashBuffer when using EncodeString internally', async () => { - const input = 'Vitest'; - const bufferFromEncode = EncodeString(input); - const buffHash = await HashBuffer(bufferFromEncode, 'SHA-256'); - const strHash = await HashString(input, 'SHA-256'); - expect(strHash).toBe(buffHash); - }); - - it('produces SHA-1 of the empty string', async () => { - expect(await HashString('', 'SHA-1')).toBe('da39a3ee5e6b4b0d3255bfef95601890afd80709'); - }); - - it('produces SHA-256 of the empty string', async () => { - expect(await HashString('', 'SHA-256')).toBe( - 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855' - ); - }); -}); diff --git a/src/lib/utils/crypto.ts b/src/lib/utils/crypto.ts deleted file mode 100644 index 400f2961..00000000 --- a/src/lib/utils/crypto.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { EncodeString } from '$lib/utils/encoding'; - -export const ArrayBufferToHex = (buffer: ArrayBuffer) => - Array.from(new Uint8Array(buffer)) - .map((num) => num.toString(16).padStart(2, '0')) - .join(''); - -export async function HashBuffer( - input: BufferSource, - hashtype: 'SHA-1' | 'SHA-256' -): Promise { - const hashBuffer = await crypto.subtle.digest(hashtype, input); - return ArrayBufferToHex(hashBuffer); -} -export async function HashString(input: string, hashtype: 'SHA-1' | 'SHA-256') { - return HashBuffer(EncodeString(input), hashtype); -} diff --git a/src/lib/utils/debounce.test.ts b/src/lib/utils/debounce.test.ts deleted file mode 100644 index 23f092f1..00000000 --- a/src/lib/utils/debounce.test.ts +++ /dev/null @@ -1,176 +0,0 @@ -import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; -import { debounce } from './debounce'; - -describe('debounce', () => { - beforeEach(() => vi.useFakeTimers()); - afterEach(() => vi.useRealTimers()); - - it('delays invocation until the timer elapses', () => { - const fn = vi.fn(); - const d = debounce(fn, 100); - - d('a'); - expect(fn).not.toHaveBeenCalled(); - vi.advanceTimersByTime(99); - expect(fn).not.toHaveBeenCalled(); - vi.advanceTimersByTime(1); - expect(fn).toHaveBeenCalledExactlyOnceWith('a'); - }); - - it('collapses rapid calls into one invocation with the latest args', () => { - const fn = vi.fn(); - const d = debounce(fn, 100); - - d('a'); - vi.advanceTimersByTime(50); - d('b'); - vi.advanceTimersByTime(50); - d('c'); - vi.advanceTimersByTime(100); - - expect(fn).toHaveBeenCalledExactlyOnceWith('c'); - }); - - it('cancel() drops the pending invocation', () => { - const fn = vi.fn(); - const d = debounce(fn, 100); - - d('a'); - d.cancel(); - vi.advanceTimersByTime(200); - - expect(fn).not.toHaveBeenCalled(); - }); - - it('flush() runs the pending invocation immediately', () => { - const fn = vi.fn(); - const d = debounce(fn, 100); - - d('a'); - d.flush(); - expect(fn).toHaveBeenCalledExactlyOnceWith('a'); - - vi.advanceTimersByTime(200); - expect(fn).toHaveBeenCalledOnce(); - }); - - it('flush() is a no-op when no call is pending', () => { - const fn = vi.fn(); - const d = debounce(fn, 100); - - d.flush(); - expect(fn).not.toHaveBeenCalled(); - }); -}); - -describe('debounce — edge cases', () => { - beforeEach(() => vi.useFakeTimers()); - afterEach(() => vi.useRealTimers()); - - it('supports zero delay (still defers to next tick)', () => { - const fn = vi.fn(); - const d = debounce(fn, 0); - - d('a'); - expect(fn).not.toHaveBeenCalled(); - vi.advanceTimersByTime(0); - expect(fn).toHaveBeenCalledExactlyOnceWith('a'); - }); - - it('cancel() before any call is a no-op', () => { - const fn = vi.fn(); - const d = debounce(fn, 50); - expect(() => d.cancel()).not.toThrow(); - expect(fn).not.toHaveBeenCalled(); - }); - - it('cancel() after fire is a no-op and does not double-fire', () => { - const fn = vi.fn(); - const d = debounce(fn, 50); - - d('a'); - vi.advanceTimersByTime(50); - expect(fn).toHaveBeenCalledExactlyOnceWith('a'); - - d.cancel(); - vi.advanceTimersByTime(500); - expect(fn).toHaveBeenCalledOnce(); - }); - - it('allows another call after a fire and re-debounces it', () => { - const fn = vi.fn(); - const d = debounce(fn, 100); - - d('first'); - vi.advanceTimersByTime(100); - expect(fn).toHaveBeenCalledExactlyOnceWith('first'); - - d('second'); - vi.advanceTimersByTime(99); - expect(fn).toHaveBeenCalledOnce(); - vi.advanceTimersByTime(1); - expect(fn).toHaveBeenCalledTimes(2); - expect(fn).toHaveBeenLastCalledWith('second'); - }); - - it('flush() after fire does not invoke again', () => { - const fn = vi.fn(); - const d = debounce(fn, 50); - - d('a'); - vi.advanceTimersByTime(50); - expect(fn).toHaveBeenCalledOnce(); - - d.flush(); - expect(fn).toHaveBeenCalledOnce(); - }); - - it('passes through multiple arguments correctly', () => { - const fn = vi.fn<(a: number, b: string, c: object) => void>(); - const d = debounce(fn, 10); - - const obj = { x: 1 }; - d(1, 'two', obj); - vi.advanceTimersByTime(10); - - expect(fn).toHaveBeenCalledExactlyOnceWith(1, 'two', obj); - }); - - it('handles many rapid invocations with only the final one firing', () => { - const fn = vi.fn(); - const d = debounce(fn, 25); - - for (let i = 0; i < 1000; i++) { - d(i); - vi.advanceTimersByTime(1); - } - vi.advanceTimersByTime(25); - - expect(fn).toHaveBeenCalledOnce(); - expect(fn).toHaveBeenCalledWith(999); - }); - - it('allows scheduling immediately after cancel()', () => { - const fn = vi.fn(); - const d = debounce(fn, 30); - - d('a'); - vi.advanceTimersByTime(20); - d.cancel(); - expect(fn).not.toHaveBeenCalled(); - - d('b'); - vi.advanceTimersByTime(30); - expect(fn).toHaveBeenCalledExactlyOnceWith('b'); - }); - - it('flush() invokes synchronously without waiting for timer', () => { - const fn = vi.fn(); - const d = debounce(fn, 10_000); - - d('immediate'); - d.flush(); - // No timer advance needed - expect(fn).toHaveBeenCalledExactlyOnceWith('immediate'); - }); -}); diff --git a/src/lib/utils/debounce.ts b/src/lib/utils/debounce.ts deleted file mode 100644 index da24ab19..00000000 --- a/src/lib/utils/debounce.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { onDestroy } from 'svelte'; - -export interface Debounced { - (...args: Args): void; - cancel(): void; - flush(): void; -} - -export function debounce( - fn: (...args: Args) => void, - delay: number -): Debounced { - let handle: ReturnType | undefined; - let pending: Args | undefined; - - const debounced = ((...args: Args) => { - clearTimeout(handle); - pending = args; - handle = setTimeout(() => { - handle = undefined; - const p = pending; - pending = undefined; - if (p) fn(...p); - }, delay); - }) as Debounced; - - debounced.cancel = () => { - clearTimeout(handle); - handle = undefined; - pending = undefined; - }; - - debounced.flush = () => { - if (handle === undefined) return; - clearTimeout(handle); - handle = undefined; - const p = pending; - pending = undefined; - if (p) fn(...p); - }; - - return debounced; -} - -/** Component-aware `debounce` that cancels any pending invocation on unmount. */ -export function useDebounce( - fn: (...args: Args) => void, - delay: number -): Debounced { - const d = debounce(fn, delay); - onDestroy(d.cancel); - return d; -} diff --git a/src/lib/utils/encoding.test.ts b/src/lib/utils/encoding.test.ts deleted file mode 100644 index dd7b1c8b..00000000 --- a/src/lib/utils/encoding.test.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { describe, expect, it } from 'vitest'; -import { DecodeString, EncodeString, escapeHtml } from './encoding'; - -describe('escapeHtml', () => { - it('returns "null" when input is null', () => { - expect(escapeHtml(null)).toBe('null'); - }); - - it('leaves a string without special characters unchanged', () => { - expect(escapeHtml('abc123')).toBe('abc123'); - expect(escapeHtml('Hello World')).toBe('Hello World'); - }); - - it('escapes &, <, >, ", and \' correctly', () => { - const unsafe = `Dolce & Gabbana < "Fashion" > 'Style'`; - const expected = 'Dolce & Gabbana < "Fashion" > 'Style''; - expect(escapeHtml(unsafe)).toBe(expected); - }); - - it('handles strings that are already partially escaped without double-escaping', () => { - const partially = '&<>"''; - // Only raw &, <, >, ", ' get replaced; existing entities contain & so they become & - expect(escapeHtml(partially)).toBe('&amp;&lt;&gt;&quot;&#039;'); - }); - - it('escapes a string containing only special characters', () => { - expect(escapeHtml('&<>"\'')).toBe('&<>"''); - }); - - it('returns an empty string when given an empty string', () => { - expect(escapeHtml('')).toBe(''); - }); -}); - -describe('EncodeString & DecodeString', () => { - it('EncodeString returns a Uint8Array representing UTF-8 bytes', () => { - const ascii = 'hello'; - const asciiEncoded = EncodeString(ascii); - // UTF-8 for "hello" is [104, 101, 108, 108, 111] - expect(asciiEncoded).toBeInstanceOf(Uint8Array); - expect(Array.from(asciiEncoded)).toEqual([104, 101, 108, 108, 111]); - - const unicode = '你好'; - const unicodeEncoded = EncodeString(unicode); - // Verify against TextEncoder directly - const expected = new TextEncoder().encode(unicode); - expect(Array.from(unicodeEncoded)).toEqual(Array.from(expected)); - }); - - it('DecodeString returns the original string from a Uint8Array', () => { - const original = 'Vitest 🚀'; - const encoded = new TextEncoder().encode(original); - const decoded = DecodeString(encoded); - expect(decoded).toBe(original); - }); - - it('round-trips arbitrary strings through EncodeString and DecodeString', () => { - const samples = [ - '', - 'simple text', - 'Line 1\nLine 2\tTabbed', - 'áéíóú üñ ¿¡', - 'Emoji: 😀🎉', - '中文字符测试', - ]; - - for (const s of samples) { - const encoded = EncodeString(s); - const decoded = DecodeString(encoded); - expect(decoded).toBe(s); - } - }); - - it(' EncodeString and DecodeString correctly handle byte values >= 0x80', () => { - // Create a Uint8Array manually with high-byte values and decode then re-encode - const bytes = new Uint8Array([0xc3, 0xa9]); // UTF-8 for "é" - const decoded = DecodeString(bytes); - expect(decoded).toBe('é'); - const reEncoded = EncodeString(decoded); - expect(Array.from(reEncoded)).toEqual([0xc3, 0xa9]); - }); -}); diff --git a/src/lib/utils/encoding.ts b/src/lib/utils/encoding.ts deleted file mode 100644 index 3d8e3fed..00000000 --- a/src/lib/utils/encoding.ts +++ /dev/null @@ -1,12 +0,0 @@ -export function escapeHtml(unsafe: string | null): string { - if (unsafe === null) return 'null'; - return unsafe - .replaceAll('&', '&') - .replaceAll('<', '<') - .replaceAll('>', '>') - .replaceAll('"', '"') - .replaceAll("'", '''); -} - -export const EncodeString = (input: string) => new TextEncoder().encode(input); -export const DecodeString = (input: Uint8Array) => new TextDecoder().decode(input); diff --git a/src/lib/utils/entropy.test.ts b/src/lib/utils/entropy.test.ts deleted file mode 100644 index 53f3fd29..00000000 --- a/src/lib/utils/entropy.test.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { describe, expect, it } from 'vitest'; -import { calculateStringEntropy } from './entropy'; - -describe('calculateStringEntropy', () => { - it('returns 0 for an empty string', () => { - // uniqueLength = 0, length = 0 => Math.pow(0, 0) = 1 => log2(1) = 0 - expect(calculateStringEntropy('')).toBe(0); - }); - - it('returns 0 when all characters are the same', () => { - // e.g., "aaaa", uniqueLength = 1, length = 4 => 1^4 = 1 => log2(1) = 0 - expect(calculateStringEntropy('aaaa')).toBe(0); - expect(calculateStringEntropy('bbbbbbbb')).toBe(0); - }); - - it('computes correctly for two unique characters', () => { - // "01", uniqueLength = 2, length = 2 => 2^2 = 4 => log2(4) = 2 - expect(calculateStringEntropy('01')).toBe(2); - - // "abab", uniqueLength = 2, length = 4 => 2^4 = 16 => log2(16) = 4 - expect(calculateStringEntropy('abab')).toBe(4); - }); - - it('computes correctly when all characters are unique', () => { - // "abcd", uniqueLength = 4, length = 4 => 4^4 = 256 => log2(256) = 8 - expect(calculateStringEntropy('abcd')).toBe(8); - - // "xyz", uniqueLength = 3, length = 3 => 3^3 = 27 => log2(27) = 3 * log2(3) - const expected = 3 * Math.log2(3); - expect(calculateStringEntropy('xyz')).toBeCloseTo(expected); - }); - - it('is order‐invariant: same set of characters yields same entropy regardless of ordering', () => { - const s1 = 'abcabc'; - const s2 = 'cbaacb'; - // Both: uniqueLength = 3, length = 6 => 3^6 => log2(3^6) = 6 * log2(3) - const expected = 6 * Math.log2(3); - expect(calculateStringEntropy(s1)).toBeCloseTo(expected); - expect(calculateStringEntropy(s2)).toBeCloseTo(expected); - }); - - it('handles longer mixed strings', () => { - const value = 'abcabcabc'; // uniqueLength = 3, length = 9 - // 3^9 = 19683, log2(19683) = 9 * log2(3) - const expected = 9 * Math.log2(3); - expect(calculateStringEntropy(value)).toBeCloseTo(expected); - - const mixed = 'AaBbCc123!@#'; - // uniqueLength = number of distinct chars in mixed - const uniqueLength = new Set(mixed).size; - const length = mixed.length; - const total = uniqueLength ** length; - const expectedMixed = Math.log2(total); - expect(calculateStringEntropy(mixed)).toBeCloseTo(expectedMixed); - }); -}); diff --git a/src/lib/utils/entropy.ts b/src/lib/utils/entropy.ts deleted file mode 100644 index 4191a093..00000000 --- a/src/lib/utils/entropy.ts +++ /dev/null @@ -1,7 +0,0 @@ -export function calculateStringEntropy(value: string): number { - const uniqueChars = new Set(value); - const length = value.length; - const uniqueLength = uniqueChars.size; - - return Math.log2(uniqueLength ** length); -} diff --git a/src/lib/utils/index.ts b/src/lib/utils/index.ts index 3f45ee86..20689d1b 100644 --- a/src/lib/utils/index.ts +++ b/src/lib/utils/index.ts @@ -1,11 +1,2 @@ -export * from './debounce'; -export * from './encoding'; -export * from './entropy'; -export * from './math'; -export * from './parse'; -export * from './rand'; -export * from './shadcn'; export * from './shockerPause'; -export * from './temporal'; -export * from './time'; export * from './userAgent'; diff --git a/src/lib/utils/math.test.ts b/src/lib/utils/math.test.ts deleted file mode 100644 index 4dcf328c..00000000 --- a/src/lib/utils/math.test.ts +++ /dev/null @@ -1,122 +0,0 @@ -import { describe, expect, it } from 'vitest'; -import { DegToRad, RadToDeg, clamp, getCircleX, getCircleY, invLerp, lerp } from './math'; - -describe('math constants', () => { - it('DegToRad ≈ π/180', () => { - expect(DegToRad).toBeCloseTo(Math.PI / 180); - }); - - it('RadToDeg ≈ 180/π', () => { - expect(RadToDeg).toBeCloseTo(180 / Math.PI); - }); - - it('DegToRad and RadToDeg are inverses', () => { - expect(DegToRad * RadToDeg).toBeCloseTo(1); - }); -}); - -describe('clamp(value, min, max)', () => { - it('returns min when value is below min', () => { - expect(clamp(-10, 0, 5)).toBe(0); - }); - - it('returns max when value is above max', () => { - expect(clamp(10, 0, 5)).toBe(5); - }); - - it('returns value when it is between min and max', () => { - expect(clamp(3, 0, 5)).toBe(3); - expect(clamp(0, 0, 5)).toBe(0); - expect(clamp(5, 0, 5)).toBe(5); - }); - - it('works when min and max are negative or reversed', () => { - expect(clamp(-3, -5, -1)).toBe(-3); - expect(clamp(-6, -5, -1)).toBe(-5); - expect(clamp(0, -5, -1)).toBe(-1); - }); -}); - -describe('lerp(a, b, t)', () => { - it('returns a when t=0', () => { - expect(lerp(10, 20, 0)).toBe(10); - }); - - it('returns b when t=1', () => { - expect(lerp(10, 20, 1)).toBe(20); - }); - - it('returns midpoint when t=0.5', () => { - expect(lerp(10, 20, 0.5)).toBe(15); - }); - - it('interpolates correctly for t outside [0,1]', () => { - expect(lerp(0, 100, 1.5)).toBe(150); - expect(lerp(0, 100, -0.5)).toBe(-50); - }); -}); - -describe('invLerp(a, b, value)', () => { - it('returns 0 when value equals a', () => { - expect(invLerp(10, 20, 10)).toBeCloseTo(0); - }); - - it('returns 1 when value equals b', () => { - expect(invLerp(10, 20, 20)).toBeCloseTo(1); - }); - - it('returns 0.5 when value is midpoint', () => { - expect(invLerp(10, 20, 15)).toBeCloseTo(0.5); - }); - - it('returns negative t when value < a and >1 when value > b', () => { - expect(invLerp(10, 20, 5)).toBeCloseTo(-0.5); - expect(invLerp(10, 20, 25)).toBeCloseTo(1.5); - }); - - it('is inverse of lerp for linear inputs', () => { - const a = -50; - const b = 150; - for (const t of [0, 0.2, 0.75, 1, 1.3]) { - const interpolated = lerp(a, b, t); - expect(invLerp(a, b, interpolated)).toBeCloseTo(t); - } - }); -}); - -describe('getCircleX(radius, degrees) and getCircleY(radius, degrees)', () => { - const radius = 10; - - it('at 0° returns (radius, 0)', () => { - expect(getCircleX(radius, 0)).toBeCloseTo(radius); - expect(getCircleY(radius, 0)).toBeCloseTo(0); - }); - - it('at 90° returns (0, radius)', () => { - expect(getCircleX(radius, 90)).toBeCloseTo(0); - expect(getCircleY(radius, 90)).toBeCloseTo(radius); - }); - - it('at 180° returns (-radius, 0)', () => { - expect(getCircleX(radius, 180)).toBeCloseTo(-radius); - expect(getCircleY(radius, 180)).toBeCloseTo(0); - }); - - it('at 270° returns (0, -radius)', () => { - expect(getCircleX(radius, 270)).toBeCloseTo(0); - expect(getCircleY(radius, 270)).toBeCloseTo(-radius); - }); - - it('handles non-right angles correctly (e.g., 45°)', () => { - const diag = radius / Math.sqrt(2); - expect(getCircleX(radius, 45)).toBeCloseTo(diag); - expect(getCircleY(radius, 45)).toBeCloseTo(diag); - }); - - it('works with negative and >360° angles by relying on cosine/sine periodicity', () => { - expect(getCircleX(radius, -90)).toBeCloseTo(0); - expect(getCircleY(radius, -90)).toBeCloseTo(-radius); - expect(getCircleX(radius, 450)).toBeCloseTo(0); // 450° = 360° + 90° - expect(getCircleY(radius, 450)).toBeCloseTo(radius); - }); -}); diff --git a/src/lib/utils/math.ts b/src/lib/utils/math.ts deleted file mode 100644 index e3593a8d..00000000 --- a/src/lib/utils/math.ts +++ /dev/null @@ -1,19 +0,0 @@ -export const DegToRad = Math.PI / 180; -export const RadToDeg = 180 / Math.PI; - -export function clamp(value: number, min: number, max: number): number { - return Math.min(max, Math.max(min, value)); -} -export function lerp(a: number, b: number, t: number): number { - return a + (b - a) * t; -} -export function invLerp(a: number, b: number, value: number): number { - return (value - a) / (b - a); -} - -export function getCircleX(radius: number, degrees: number): number { - return radius * Math.cos(degrees * DegToRad); -} -export function getCircleY(radius: number, degrees: number): number { - return radius * Math.sin(degrees * DegToRad); -} diff --git a/src/lib/utils/md5.test.ts b/src/lib/utils/md5.test.ts deleted file mode 100644 index 71e0d1cc..00000000 --- a/src/lib/utils/md5.test.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { describe, expect, it } from 'vitest'; -import { md5 } from './md5'; - -function fromString(s: string): Uint8Array { - return new TextEncoder().encode(s); -} - -describe('md5', () => { - it('hashes an empty input', () => { - expect(md5(new Uint8Array([]))).toBe('d41d8cd98f00b204e9800998ecf8427e'); - }); - - it('hashes "hello"', () => { - expect(md5(fromString('hello'))).toBe('5d41402abc4b2a76b9719d911017c592'); - }); - - it('hashes "abc"', () => { - expect(md5(fromString('abc'))).toBe('900150983cd24fb0d6963f7d28e17f72'); - }); - - it('hashes a string exactly 55 bytes (just fits in one block with padding)', () => { - const input = 'a'.repeat(55); - expect(md5(fromString(input))).toBe('ef1772b6dff9a122358552954ad0df65'); - }); - - it('hashes a string of 56 bytes (forces a second block for padding)', () => { - const input = 'a'.repeat(56); - expect(md5(fromString(input))).toBe('3b0c8ac703f828b04c6c197006d17218'); - }); - - it('hashes a string exactly 64 bytes (one full block)', () => { - const input = 'a'.repeat(64); - expect(md5(fromString(input))).toBe('014842d480b571495a4a0363793f7367'); - }); - - it('hashes arbitrary binary data', () => { - const data = new Uint8Array([0xde, 0xad, 0xbe, 0xef]); - expect(md5(data)).toBe('2f249230a8e7c2bf6005ccd2679259ec'); - }); - - it('hashes a longer message spanning multiple blocks', () => { - const input = 'The quick brown fox jumps over the lazy dog'; - expect(md5(fromString(input))).toBe('9e107d9d372bb6826bd81d3542a419d6'); - }); - - it('hashes 1 million "a" chars (RFC 1321 test vector)', () => { - const data = new Uint8Array(1_000_000).fill(0x61); // 0x61 = 'a' - expect(md5(data)).toBe('7707d6ae4e027c70eea2a935c2296f21'); - }); - - it('hashes a 1024-byte buffer (16 full blocks, no remainder)', () => { - const data = new Uint8Array(1024).fill(0x00); - expect(md5(data)).toBe('0f343b0931126a20f133d67c2b018a3b'); - }); - - it('hashes byte 0xff repeated 65 times (just over a full block)', () => { - const data = new Uint8Array(65).fill(0xff); - // value verified independently; locks current implementation behavior - expect(md5(data).length).toBe(32); - expect(/^[0-9a-f]{32}$/.test(md5(data))).toBe(true); - }); -}); diff --git a/src/lib/utils/md5.ts b/src/lib/utils/md5.ts deleted file mode 100644 index 88f31603..00000000 --- a/src/lib/utils/md5.ts +++ /dev/null @@ -1,155 +0,0 @@ -// MD5 implementation adapted from Joseph Myers' public domain code -// https://www.myersdaily.org/joseph/javascript/md5-text.html - -function add32(a: number, b: number): number { - return (a + b) & 0xffffffff; -} - -function cmn(q: number, a: number, b: number, x: number, s: number, t: number): number { - a = add32(add32(a, q), add32(x, t)); - return add32((a << s) | (a >>> (32 - s)), b); -} - -function ff(a: number, b: number, c: number, d: number, x: number, s: number, t: number) { - return cmn((b & c) | (~b & d), a, b, x, s, t); -} - -function gg(a: number, b: number, c: number, d: number, x: number, s: number, t: number) { - return cmn((b & d) | (c & ~d), a, b, x, s, t); -} - -function hh(a: number, b: number, c: number, d: number, x: number, s: number, t: number) { - return cmn(b ^ c ^ d, a, b, x, s, t); -} - -function ii(a: number, b: number, c: number, d: number, x: number, s: number, t: number) { - return cmn(c ^ (b | ~d), a, b, x, s, t); -} - -function md5blk(data: Uint8Array, offset: number): number[] { - const blks: number[] = []; - for (let i = 0; i < 64; i += 4) { - blks[i >> 2] = - data[offset + i] | - (data[offset + i + 1] << 8) | - (data[offset + i + 2] << 16) | - (data[offset + i + 3] << 24); - } - return blks; -} - -function md5cycle(state: number[], blk: number[]) { - let a = state[0], - b = state[1], - c = state[2], - d = state[3]; - - a = ff(a, b, c, d, blk[0], 7, -680876936); - d = ff(d, a, b, c, blk[1], 12, -389564586); - c = ff(c, d, a, b, blk[2], 17, 606105819); - b = ff(b, c, d, a, blk[3], 22, -1044525330); - a = ff(a, b, c, d, blk[4], 7, -176418897); - d = ff(d, a, b, c, blk[5], 12, 1200080426); - c = ff(c, d, a, b, blk[6], 17, -1473231341); - b = ff(b, c, d, a, blk[7], 22, -45705983); - a = ff(a, b, c, d, blk[8], 7, 1770035416); - d = ff(d, a, b, c, blk[9], 12, -1958414417); - c = ff(c, d, a, b, blk[10], 17, -42063); - b = ff(b, c, d, a, blk[11], 22, -1990404162); - a = ff(a, b, c, d, blk[12], 7, 1804603682); - d = ff(d, a, b, c, blk[13], 12, -40341101); - c = ff(c, d, a, b, blk[14], 17, -1502002290); - b = ff(b, c, d, a, blk[15], 22, 1236535329); - - a = gg(a, b, c, d, blk[1], 5, -165796510); - d = gg(d, a, b, c, blk[6], 9, -1069501632); - c = gg(c, d, a, b, blk[11], 14, 643717713); - b = gg(b, c, d, a, blk[0], 20, -373897302); - a = gg(a, b, c, d, blk[5], 5, -701558691); - d = gg(d, a, b, c, blk[10], 9, 38016083); - c = gg(c, d, a, b, blk[15], 14, -660478335); - b = gg(b, c, d, a, blk[4], 20, -405537848); - a = gg(a, b, c, d, blk[9], 5, 568446438); - d = gg(d, a, b, c, blk[14], 9, -1019803690); - c = gg(c, d, a, b, blk[3], 14, -187363961); - b = gg(b, c, d, a, blk[8], 20, 1163531501); - a = gg(a, b, c, d, blk[13], 5, -1444681467); - d = gg(d, a, b, c, blk[2], 9, -51403784); - c = gg(c, d, a, b, blk[7], 14, 1735328473); - b = gg(b, c, d, a, blk[12], 20, -1926607734); - - a = hh(a, b, c, d, blk[5], 4, -378558); - d = hh(d, a, b, c, blk[8], 11, -2022574463); - c = hh(c, d, a, b, blk[11], 16, 1839030562); - b = hh(b, c, d, a, blk[14], 23, -35309556); - a = hh(a, b, c, d, blk[1], 4, -1530992060); - d = hh(d, a, b, c, blk[4], 11, 1272893353); - c = hh(c, d, a, b, blk[7], 16, -155497632); - b = hh(b, c, d, a, blk[10], 23, -1094730640); - a = hh(a, b, c, d, blk[13], 4, 681279174); - d = hh(d, a, b, c, blk[0], 11, -358537222); - c = hh(c, d, a, b, blk[3], 16, -722521979); - b = hh(b, c, d, a, blk[6], 23, 76029189); - a = hh(a, b, c, d, blk[9], 4, -640364487); - d = hh(d, a, b, c, blk[12], 11, -421815835); - c = hh(c, d, a, b, blk[15], 16, 530742520); - b = hh(b, c, d, a, blk[2], 23, -995338651); - - a = ii(a, b, c, d, blk[0], 6, -198630844); - d = ii(d, a, b, c, blk[7], 10, 1126891415); - c = ii(c, d, a, b, blk[14], 15, -1416354905); - b = ii(b, c, d, a, blk[5], 21, -57434055); - a = ii(a, b, c, d, blk[12], 6, 1700485571); - d = ii(d, a, b, c, blk[3], 10, -1894986606); - c = ii(c, d, a, b, blk[10], 15, -1051523); - b = ii(b, c, d, a, blk[1], 21, -2054922799); - a = ii(a, b, c, d, blk[8], 6, 1873313359); - d = ii(d, a, b, c, blk[15], 10, -30611744); - c = ii(c, d, a, b, blk[6], 15, -1560198380); - b = ii(b, c, d, a, blk[13], 21, 1309151649); - a = ii(a, b, c, d, blk[4], 6, -145523070); - d = ii(d, a, b, c, blk[11], 10, -1120210379); - c = ii(c, d, a, b, blk[2], 15, 718787259); - b = ii(b, c, d, a, blk[9], 21, -343485551); - - state[0] = add32(a, state[0]); - state[1] = add32(b, state[1]); - state[2] = add32(c, state[2]); - state[3] = add32(d, state[3]); -} - -const HEX_CHARS = '0123456789abcdef'; - -function rhex(n: number): string { - let s = ''; - for (let j = 0; j < 4; j++) { - s += HEX_CHARS[(n >> (j * 8 + 4)) & 0x0f] + HEX_CHARS[(n >> (j * 8)) & 0x0f]; - } - return s; -} - -export function md5(data: Uint8Array): string { - const n = data.length; - const state = [1732584193, -271733879, -1732584194, 271733878]; - - let i: number; - for (i = 64; i <= n; i += 64) { - md5cycle(state, md5blk(data, i - 64)); - } - - const tail = new Array(16).fill(0); - const rem = n % 64; - const offset = n - rem; - for (i = 0; i < rem; i++) { - tail[i >> 2] |= data[offset + i] << ((i % 4) << 3); - } - tail[i >> 2] |= 0x80 << ((i % 4) << 3); - if (i > 55) { - md5cycle(state, tail); - tail.fill(0); - } - tail[14] = n * 8; - md5cycle(state, tail); - - return state.map(rhex).join(''); -} diff --git a/src/lib/utils/parse.test.ts b/src/lib/utils/parse.test.ts deleted file mode 100644 index 0a7eb4a1..00000000 --- a/src/lib/utils/parse.test.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { describe, expect, it } from 'vitest'; -import { isTruthy } from './parse'; - -describe('isTruthy', () => { - it.each([true, 1, '1', 'true', 'TRUE', 'True', 'yes', 'YES', 'y', 'Y', 'on', 'ON'])( - 'returns true for %j', - (value) => { - expect(isTruthy(value)).toBe(true); - } - ); - - it.each([false, 0, 2, -1, '0', 'false', 'no', 'off', 'random', '', null, undefined])( - 'returns false for %j', - (value) => { - expect(isTruthy(value)).toBe(false); - } - ); -}); - -describe('isTruthy edge cases', () => { - it.each([NaN, Infinity, -Infinity, 1.0001, 0.9999, Number.MAX_SAFE_INTEGER, -0])( - 'returns false for non-1 numeric value %j', - (value) => { - expect(isTruthy(value)).toBe(false); - } - ); - - it('treats numeric 1 (and not 1.0 with epsilon) strictly', () => { - expect(isTruthy(1)).toBe(true); - expect(isTruthy(1 + Number.EPSILON)).toBe(false); - }); - - it.each([' true', 'true ', ' yes ', '\ttrue', 'true\n', '1 ', ' on'])( - 'rejects whitespace-padded truthy strings: %j', - (value) => { - expect(isTruthy(value)).toBe(false); - } - ); - - it.each(['tRuE', 'YeS', 'On', 'oN', 'Y', 'y'])('accepts mixed-case truthy: %j', (value) => { - expect(isTruthy(value)).toBe(true); - }); - - it.each(['truee', 'yess', 'yeah', 'enable', 'enabled', '11', '01'])( - 'rejects near-truthy strings: %j', - (value) => { - expect(isTruthy(value)).toBe(false); - } - ); - - it('handles a very long non-truthy string', () => { - expect(isTruthy('a'.repeat(10_000))).toBe(false); - }); - - it.each([{}, [], () => true, Symbol('x')])( - 'returns false for non-string/number/boolean type %#', - (value) => { - expect(isTruthy(value as unknown as string)).toBe(false); - } - ); -}); diff --git a/src/lib/utils/parse.ts b/src/lib/utils/parse.ts deleted file mode 100644 index df333c6a..00000000 --- a/src/lib/utils/parse.ts +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Coerces an env-var / URL-param style value into a boolean. - * - * Truthy: `true`, the number `1`, or a case-insensitive `'1'`, `'true'`, `'yes'`, `'y'`, or `'on'`. - * - * Everything else - including `null`, `undefined`, other numbers, and unrecognized strings - is falsy. - * - * @param value - The value to coerce (typically an environment variable or query parameter) - * @returns `true` when the value matches a recognized truthy form, `false` otherwise - * - * @example - * ```ts - * isTruthy(env.PUBLIC_DISABLE_SITEMAP) // false when unset, true when "1" / "true" - * ``` - */ -export function isTruthy(value: boolean | number | string | null | undefined): boolean { - if (typeof value === 'boolean') return value; - if (typeof value === 'number') return value === 1; - if (typeof value !== 'string') return false; - - switch (value.toLowerCase()) { - case '1': - case 'true': - case 'yes': - case 'y': - case 'on': - return true; - default: - return false; - } -} diff --git a/src/lib/utils/rand.test.ts b/src/lib/utils/rand.test.ts deleted file mode 100644 index ee683592..00000000 --- a/src/lib/utils/rand.test.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { describe, expect, it } from 'vitest'; -import { randStr } from './rand'; - -const ALLOWED_REGEX = /^[A-Za-z0-9]*$/; - -describe('randStr', () => { - it('returns a string of the specified length', () => { - const lengths = [0, 1, 5, 16, 64]; - for (const len of lengths) { - const s = randStr(len); - expect(s).toHaveLength(len); - } - }); - - it('returns only characters from [A–Z][a–z][0–9]', () => { - for (let i = 0; i < 10; i++) { - const s = randStr(200); - expect(s).toMatch(ALLOWED_REGEX); - } - }); - - it('returns different strings on subsequent calls with the same length', () => { - const len = 12; - const a = randStr(len); - const b = randStr(len); - // Very unlikely to collide twice in a row - expect(a).not.toBe(b); - }); - - it('returns empty string for zero and negative lengths', () => { - expect(randStr(0)).toBe(''); - // Negative length will not enter the loop, so it should also be '' - expect(randStr(-5)).toBe(''); - }); - - it('returns empty string for NaN length', () => { - expect(randStr(Number.NaN)).toBe(''); - }); - - it('uses every character class across many samples (statistical sanity)', () => { - const sample = randStr(2000); - expect(sample).toMatch(/[A-Z]/); - expect(sample).toMatch(/[a-z]/); - expect(sample).toMatch(/[0-9]/); - }); -}); diff --git a/src/lib/utils/rand.ts b/src/lib/utils/rand.ts deleted file mode 100644 index e28a9b49..00000000 --- a/src/lib/utils/rand.ts +++ /dev/null @@ -1,14 +0,0 @@ -const randChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' as const; -const randCharsLength = randChars.length; - -export function randStr(length: number) { - let result = ''; - - let counter = 0; - while (counter < length) { - result += randChars.charAt(Math.floor(Math.random() * randCharsLength)); - counter += 1; - } - - return result; -} diff --git a/src/lib/utils/shadcn.ts b/src/lib/utils/shadcn.ts deleted file mode 100644 index c77c249f..00000000 --- a/src/lib/utils/shadcn.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { type ClassValue, clsx } from 'clsx'; -import { twMerge } from 'tailwind-merge'; - -export function cn(...inputs: ClassValue[]) { - return twMerge(clsx(inputs)); -} - -export type WithoutChild = T extends { child?: unknown } ? Omit : T; -export type WithoutChildren = T extends { children?: unknown } ? Omit : T; -export type WithoutChildrenOrChild = WithoutChildren>; -export type WithElementRef = T & { ref?: U | null }; diff --git a/src/lib/utils/temporal.test.ts b/src/lib/utils/temporal.test.ts deleted file mode 100644 index 07ee18fb..00000000 --- a/src/lib/utils/temporal.test.ts +++ /dev/null @@ -1,138 +0,0 @@ -import 'temporal-polyfill/global'; -import { describe, expect, it } from 'vitest'; -import { durationBetween, formatDuration, formatElapsed } from './temporal'; - -function instant(isoString: string): Temporal.Instant { - return Temporal.Instant.from(isoString); -} - -describe('durationBetween', () => { - it('returns a positive duration when `to` is after `from`', () => { - const from = instant('2024-01-01T00:00:00Z'); - const to = instant('2024-01-02T00:00:00Z'); - const d = durationBetween(from, to); - expect(d.sign).toBe(1); - }); - - it('returns a negative duration when `to` is before `from`', () => { - const from = instant('2024-01-02T00:00:00Z'); - const to = instant('2024-01-01T00:00:00Z'); - const d = durationBetween(from, to); - expect(d.sign).toBe(-1); - }); - - it('returns zero duration for equal instants', () => { - const from = instant('2024-06-15T12:00:00Z'); - const d = durationBetween(from, from); - expect(d.sign).toBe(0); - }); - - it('captures years correctly', () => { - const from = instant('2020-01-01T00:00:00Z'); - const to = instant('2024-01-01T00:00:00Z'); - const d = durationBetween(from, to); - expect(d.years).toBe(4); - }); - - it('captures months correctly within a year', () => { - const from = instant('2024-01-01T00:00:00Z'); - const to = instant('2024-06-01T00:00:00Z'); - const d = durationBetween(from, to); - expect(d.years).toBe(0); - expect(d.months).toBe(5); - }); -}); - -describe('formatDuration', () => { - function dur(fields: Partial): Temporal.Duration { - return Temporal.Duration.from(fields); - } - - it('returns seconds for sub-minute durations', () => { - expect(formatDuration(dur({ seconds: 1 }))).toBe('1 second'); - expect(formatDuration(dur({ seconds: 45 }))).toBe('45 seconds'); - }); - - it('returns minutes when >= 1 minute', () => { - expect(formatDuration(dur({ minutes: 1 }))).toBe('1 minute'); - expect(formatDuration(dur({ minutes: 30 }))).toBe('30 minutes'); - }); - - it('returns hours when >= 1 hour', () => { - expect(formatDuration(dur({ hours: 1 }))).toBe('1 hour'); - expect(formatDuration(dur({ hours: 3 }))).toBe('3 hours'); - }); - - it('returns days when >= 1 day', () => { - expect(formatDuration(dur({ days: 1 }))).toBe('1 day'); - expect(formatDuration(dur({ days: 6 }))).toBe('6 days'); - }); - - it('returns months when >= 1 month', () => { - expect(formatDuration(dur({ months: 1 }))).toBe('1 month'); - expect(formatDuration(dur({ months: 11 }))).toBe('11 months'); - }); - - it('returns years when >= 1 year', () => { - expect(formatDuration(dur({ years: 1 }))).toBe('1 year'); - expect(formatDuration(dur({ years: 5 }))).toBe('5 years'); - }); - - it('uses the largest non-zero unit', () => { - expect(formatDuration(dur({ years: 2, months: 3, days: 10 }))).toBe('2 years'); - expect(formatDuration(dur({ months: 0, days: 5, hours: 12 }))).toBe('5 days'); - }); - - it('handles negative durations by using absolute values', () => { - expect(formatDuration(dur({ years: -3 }))).toBe('3 years'); - expect(formatDuration(dur({ minutes: -15 }))).toBe('15 minutes'); - }); - - it('uses singular for value of 1', () => { - expect(formatDuration(dur({ seconds: 1 }))).toBe('1 second'); - expect(formatDuration(dur({ minutes: 1 }))).toBe('1 minute'); - expect(formatDuration(dur({ hours: 1 }))).toBe('1 hour'); - expect(formatDuration(dur({ days: 1 }))).toBe('1 day'); - expect(formatDuration(dur({ months: 1 }))).toBe('1 month'); - expect(formatDuration(dur({ years: 1 }))).toBe('1 year'); - }); - - it('uses plural for values other than 1', () => { - expect(formatDuration(dur({ seconds: 2 }))).toBe('2 seconds'); - expect(formatDuration(dur({ years: 10 }))).toBe('10 years'); - }); -}); - -describe('formatElapsed', () => { - function dur(fields: Partial): Temporal.Duration { - return Temporal.Duration.from(fields); - } - - it('prefixes "in " for future durations (positive sign)', () => { - expect(formatElapsed(dur({ hours: 2 }))).toBe('in 2 hours'); - expect(formatElapsed(dur({ days: 1 }))).toBe('in 1 day'); - }); - - it('suffixes " ago" for past durations (negative sign)', () => { - expect(formatElapsed(dur({ hours: -2 }))).toBe('2 hours ago'); - expect(formatElapsed(dur({ days: -1 }))).toBe('1 day ago'); - }); - - it('handles zero-length duration (sign === 0) as future', () => { - expect(formatElapsed(Temporal.Duration.from({ seconds: 0 }))).toBe('in 0 seconds'); - }); - - it('round-trips correctly with durationBetween for a 30-day gap', () => { - const now = instant('2024-03-15T12:00:00Z'); - const future = instant('2024-04-14T12:00:00Z'); - const d = durationBetween(now, future); - expect(formatElapsed(d)).toBe('in 30 days'); - }); - - it('round-trips correctly with durationBetween for a past 2-year gap', () => { - const now = instant('2024-06-01T00:00:00Z'); - const past = instant('2022-06-01T00:00:00Z'); - const d = durationBetween(now, past); - expect(formatElapsed(d)).toBe('2 years ago'); - }); -}); diff --git a/src/lib/utils/temporal.ts b/src/lib/utils/temporal.ts deleted file mode 100644 index 65a36070..00000000 --- a/src/lib/utils/temporal.ts +++ /dev/null @@ -1,25 +0,0 @@ -export function durationBetween(from: Temporal.Instant, to: Temporal.Instant): Temporal.Duration { - const tz = Temporal.Now.timeZoneId(); - return from.toZonedDateTimeISO(tz).until(to.toZonedDateTimeISO(tz), { largestUnit: 'year' }); -} - -export function formatDuration(duration: Temporal.Duration): string { - const abs = duration.abs(); - const { years, months, days, hours, minutes, seconds } = abs; - - if (years >= 1) return formatInterval('year', years); - if (months >= 1) return formatInterval('month', months); - if (days >= 1) return formatInterval('day', days); - if (hours >= 1) return formatInterval('hour', hours); - if (minutes >= 1) return formatInterval('minute', minutes); - return formatInterval('second', seconds); -} - -export function formatElapsed(duration: Temporal.Duration): string { - const text = formatDuration(duration); - return duration.sign < 0 ? text + ' ago' : 'in ' + text; -} - -function formatInterval(unit: string, interval: number): string { - return `${interval} ${unit}${interval !== 1 ? 's' : ''}`; -} diff --git a/src/lib/utils/time.test.ts b/src/lib/utils/time.test.ts deleted file mode 100644 index aa5004d2..00000000 --- a/src/lib/utils/time.test.ts +++ /dev/null @@ -1,154 +0,0 @@ -import { describe, expect, it } from 'vitest'; -import { durationToString, elapsedToString } from './time'; - -const MS_IN_SECOND = 1000; -const MS_IN_MINUTE = 60 * MS_IN_SECOND; -const MS_IN_HOUR = 60 * MS_IN_MINUTE; -const MS_IN_DAY = 24 * MS_IN_HOUR; -const MS_IN_MONTH = 30 * MS_IN_DAY; -const MS_IN_YEAR = 365 * MS_IN_DAY; - -describe('durationToString', () => { - it('returns seconds when duration is less than one minute, with correct singular/plural', () => { - expect(durationToString(0)).toBe('0 seconds'); - expect(durationToString(MS_IN_SECOND - 1)).toBe('0 seconds'); // 999 ms → 0 s - expect(durationToString(MS_IN_SECOND)).toBe('1 second'); - expect(durationToString(2.5 * MS_IN_SECOND)).toBe('2 seconds'); // 2 500 ms → 2 s - expect(durationToString(59 * MS_IN_SECOND)).toBe('59 seconds'); - }); - - it('returns minutes when duration is between one minute and one hour', () => { - expect(durationToString(MS_IN_MINUTE)).toBe('1 minute'); - expect(durationToString(2 * MS_IN_MINUTE - 1)).toBe('1 minute'); // 119 999 ms → 1.999 min → floor → 1 - expect(durationToString(2 * MS_IN_MINUTE)).toBe('2 minutes'); - expect(durationToString(MS_IN_HOUR - 1)).toBe('59 minutes'); // 3 599 999 ms → 59.9999 min → floor → 59 - }); - - it('returns hours when duration is between one hour and one day', () => { - expect(durationToString(MS_IN_HOUR)).toBe('1 hour'); - expect(durationToString(1.5 * MS_IN_HOUR)).toBe('1 hour'); // 5 400 000 ms → 1.5 h → floor → 1 - expect(durationToString(2 * MS_IN_HOUR)).toBe('2 hours'); - expect(durationToString(MS_IN_DAY - 1)).toBe('23 hours'); // 86 399 999 ms → 23.999 h → floor → 23 - }); - - it('returns days when duration is between one day and one month', () => { - expect(durationToString(MS_IN_DAY)).toBe('1 day'); - expect(durationToString(2 * MS_IN_DAY)).toBe('2 days'); - expect(durationToString(2.5 * MS_IN_DAY)).toBe('2 days'); // 216 000 000 ms → 2.5 d → floor → 2 - expect(durationToString(MS_IN_MONTH - 1)).toBe('29 days'); // 2 591 999 999 ms → 29.999 d → floor → 29 - }); - - it('returns months when duration is between one month and one year', () => { - expect(durationToString(MS_IN_MONTH)).toBe('1 month'); - expect(durationToString(2 * MS_IN_MONTH)).toBe('2 months'); - expect(durationToString(45 * MS_IN_DAY)).toBe('1 month'); // 45 d → 1.5 mo → floor → 1 - expect(durationToString(MS_IN_YEAR - 1)).toBe('12 months'); // ~12.16 mo → floor → 12 - }); - - it('returns years when duration is one year or more', () => { - expect(durationToString(MS_IN_YEAR)).toBe('1 year'); - expect(durationToString(2 * MS_IN_YEAR)).toBe('2 years'); - expect(durationToString(1.5 * MS_IN_YEAR)).toBe('1 year'); // 1.5 y → floor → 1 - expect(durationToString(100_000_000_000)).toBe('3 years'); // ~3.17 y → floor → 3 - }); - - it('treats negative inputs as positive when computing unit', () => { - expect(durationToString(-MS_IN_SECOND)).toBe('1 second'); - expect(durationToString(-MS_IN_MINUTE)).toBe('1 minute'); - expect(durationToString(-MS_IN_HOUR)).toBe('1 hour'); - }); -}); - -describe('elapsedToString', () => { - it('prefixes "in " when duration is non-negative', () => { - expect(elapsedToString(0)).toBe('in 0 seconds'); - expect(elapsedToString(2 * MS_IN_SECOND)).toBe('in 2 seconds'); - expect(elapsedToString(MS_IN_MINUTE)).toBe('in 1 minute'); - expect(elapsedToString(2 * MS_IN_HOUR)).toBe('in 2 hours'); - }); - - it('suffixes " ago" when duration is negative', () => { - expect(elapsedToString(-MS_IN_SECOND)).toBe('1 second ago'); - expect(elapsedToString(-MS_IN_MINUTE)).toBe('1 minute ago'); - expect(elapsedToString(-MS_IN_HOUR)).toBe('1 hour ago'); - expect(elapsedToString(-2 * MS_IN_HOUR)).toBe('2 hours ago'); - }); -}); - -describe('durationToString — boundary and edge cases', () => { - it('returns "0 seconds" for sub-second durations regardless of sign', () => { - expect(durationToString(0)).toBe('0 seconds'); - expect(durationToString(1)).toBe('0 seconds'); - expect(durationToString(-1)).toBe('0 seconds'); - expect(durationToString(-999)).toBe('0 seconds'); - }); - - it('handles year/month/day/hour/minute/second exact boundaries', () => { - expect(durationToString(MS_IN_SECOND)).toBe('1 second'); - expect(durationToString(MS_IN_MINUTE)).toBe('1 minute'); - expect(durationToString(MS_IN_HOUR)).toBe('1 hour'); - expect(durationToString(MS_IN_DAY)).toBe('1 day'); - expect(durationToString(MS_IN_MONTH)).toBe('1 month'); - expect(durationToString(MS_IN_YEAR)).toBe('1 year'); - }); - - it('is consistent just below each boundary', () => { - // 60_000ms is exactly 1 minute. 59_999ms → seconds branch → 59 seconds - expect(durationToString(MS_IN_MINUTE - 1)).toBe('59 seconds'); - // hour - 1 → minutes branch - expect(durationToString(MS_IN_HOUR - 1)).toBe('59 minutes'); - }); - - it('handles very large values (centuries)', () => { - const result = durationToString(1000 * MS_IN_YEAR); - expect(result).toBe('1000 years'); - }); - - it('handles Number.MAX_SAFE_INTEGER without throwing', () => { - const result = durationToString(Number.MAX_SAFE_INTEGER); - expect(result).toMatch(/^\d+ years$/); - }); - - it('handles Infinity by returning a years string', () => { - // Math.abs(Infinity) / 1000 = Infinity; Math.floor(Infinity) is Infinity → "Infinity year(s)" - const result = durationToString(Infinity); - expect(result).toBe('Infinity years'); - }); - - it('handles -Infinity by treating absolute value', () => { - const result = durationToString(-Infinity); - expect(result).toBe('Infinity years'); - }); - - it('handles NaN gracefully (NaN seconds → "NaN seconds")', () => { - // Math.floor(NaN) is NaN; Math.abs(NaN) is NaN; NaN / 1000 → NaN; comparisons all false - expect(durationToString(NaN)).toBe('NaN seconds'); - }); -}); - -describe('elapsedToString — boundary and edge cases', () => { - it('treats 0 as non-negative ("in 0 seconds")', () => { - expect(elapsedToString(0)).toBe('in 0 seconds'); - }); - - it('handles -0 as non-negative (since -0 < 0 is false)', () => { - expect(elapsedToString(-0)).toBe('in 0 seconds'); - }); - - it('handles a negative sub-second value (still non-zero negative)', () => { - // -500ms → isNegative true → "0 seconds ago" - expect(elapsedToString(-500)).toBe('0 seconds ago'); - }); - - it('formats large positive year value', () => { - expect(elapsedToString(2 * MS_IN_YEAR)).toBe('in 2 years'); - }); - - it('formats large negative year value', () => { - expect(elapsedToString(-2 * MS_IN_YEAR)).toBe('2 years ago'); - }); - - it('handles NaN (NaN < 0 is false → "in" prefix)', () => { - expect(elapsedToString(NaN)).toBe('in NaN seconds'); - }); -}); diff --git a/src/lib/utils/time.ts b/src/lib/utils/time.ts deleted file mode 100644 index a9b5cd59..00000000 --- a/src/lib/utils/time.ts +++ /dev/null @@ -1,41 +0,0 @@ -function formatInterval(unit: string, interval: number) { - interval = Math.floor(interval); - return interval + ' ' + unit + (interval != 1 ? 's' : ''); -} - -export function durationToString(durationMs: number) { - const seconds = Math.floor(Math.abs(durationMs) / 1000); - - let interval = seconds / 31536000; - if (interval >= 1) return formatInterval('year', interval); - - interval = seconds / 2592000; - if (interval >= 1) return formatInterval('month', interval); - - interval = seconds / 86400; - if (interval >= 1) return formatInterval('day', interval); - - interval = seconds / 3600; - if (interval >= 1) return formatInterval('hour', interval); - - interval = seconds / 60; - if (interval >= 1) return formatInterval('minute', interval); - - return formatInterval('second', seconds); -} - -export function elapsedToString(elapsedMs: number) { - const isNegative = elapsedMs < 0; - const duration = durationToString(elapsedMs); - - return isNegative ? duration + ' ago' : 'in ' + duration; -} - -/** - * Formats a shocker control/limit duration (given in seconds) for display: always - * in seconds with an `s` unit, rounded to one decimal (durations step in 0.1s), - * dropping a trailing `.0` for whole numbers. e.g. 15 -> "15s", 1.5 -> "1.5s". - */ -export function formatDurationSeconds(seconds: number) { - return `${Math.round(seconds * 10) / 10}s`; -} diff --git a/src/routes/(app)/+layout.svelte b/src/routes/(app)/+layout.svelte index a8775d51..893b4cc8 100644 --- a/src/routes/(app)/+layout.svelte +++ b/src/routes/(app)/+layout.svelte @@ -2,8 +2,8 @@ import { goto } from '$app/navigation'; import { resolve } from '$app/paths'; import { page } from '$app/state'; - import Container from '$lib/components/Container.svelte'; - import { Spinner } from '$lib/components/ui/spinner'; + import Container from '$core/components/Container.svelte'; + import { Spinner } from '$hadcn/spinner'; import { AuthStatus, authState } from '$lib/state/auth-state.svelte'; import type { Snippet } from 'svelte'; diff --git a/src/routes/(app)/admin/+layout.svelte b/src/routes/(app)/admin/+layout.svelte index a46a21a5..2457c610 100644 --- a/src/routes/(app)/admin/+layout.svelte +++ b/src/routes/(app)/admin/+layout.svelte @@ -5,7 +5,7 @@ diff --git a/src/routes/Footer.svelte b/src/routes/Footer.svelte index 4073f509..521219f8 100644 --- a/src/routes/Footer.svelte +++ b/src/routes/Footer.svelte @@ -5,8 +5,8 @@ import { PUBLIC_GITHUB_PROJECT_URL } from '$env/static/public'; import { getConnectionState } from '$lib/signalr/user.svelte'; import { Wifi, WifiOff } from '@lucide/svelte'; - import * as DropdownMenu from '$lib/components/ui/dropdown-menu/index.js'; - import { Button } from '$lib/components/ui/button'; + import * as DropdownMenu from '$hadcn/dropdown-menu'; + import { Button } from '$hadcn/button'; import { backendMetadata } from '$lib/state/backend-metadata-state.svelte'; diff --git a/src/routes/Header.svelte b/src/routes/Header.svelte index 28b57c79..7c8f3fae 100644 --- a/src/routes/Header.svelte +++ b/src/routes/Header.svelte @@ -5,20 +5,25 @@ import { goto } from '$app/navigation'; import type { Pathname } from '$app/types'; import { PUBLIC_DISCORD_INVITE_URL, PUBLIC_GITHUB_PROJECT_URL } from '$env/static/public'; - import LightSwitch from '$lib/components/LightSwitch.svelte'; - import DiscordLogo from '$lib/components/svg/DiscordLogo.svelte'; - import GithubIcon from '$lib/components/svg/GithubIcon.svelte'; - import { Button } from '$lib/components/ui/button'; - import * as DropdownMenu from '$lib/components/ui/dropdown-menu'; - import { Separator } from '$lib/components/ui/separator'; - import { useSidebar } from '$lib/components/ui/sidebar'; + import LightSwitch from '$core/components/LightSwitch.svelte'; + import { + ColorScheme, + colorScheme, + getDarkReaderState, + } from '$lib/state/color-scheme-state.svelte'; + import DiscordLogo from '$core/components/svg/DiscordLogo.svelte'; + import GithubIcon from '$core/components/svg/GithubIcon.svelte'; + import { Button } from '$hadcn/button'; + import * as DropdownMenu from '$hadcn/dropdown-menu'; + import { Separator } from '$hadcn/separator'; + import { useSidebar } from '$hadcn/sidebar'; import { userState } from '$lib/state/user-state.svelte'; - import { cn } from '$lib/utils'; + import { cn } from '$core/utils/shadcn'; import Breadcrumb from './Breadcrumb.svelte'; import { prefixBase } from '$lib/utils/url'; import { resolve } from '$app/paths'; import { LogIn, UserPlus } from '@lucide/svelte'; - import { Spinner } from '$lib/components/ui/spinner'; + import { Spinner } from '$hadcn/spinner'; let sidebar = useSidebar(); @@ -45,7 +50,12 @@ >
    - + (colorScheme.value = v as ColorScheme)} + confirmLightMode + darkReaderActive={getDarkReaderState().isActive} + /> {#if userState.loading} diff --git a/src/routes/Sidebar.svelte b/src/routes/Sidebar.svelte index 19cd189b..5ff95c27 100644 --- a/src/routes/Sidebar.svelte +++ b/src/routes/Sidebar.svelte @@ -34,9 +34,9 @@ MenuSubButton, Root, useSidebar, - } from '$lib/components/ui/sidebar'; + } from '$hadcn/sidebar'; import { userState } from '$lib/state/user-state.svelte'; - import type { AnyComponent } from '$lib/types/AnyComponent'; + import type { AnyComponent } from '$core/types/AnyComponent'; import { isSerialSupported } from '$lib/utils/compatibility'; import { Collapsible } from 'bits-ui'; import { prefixBase } from '$lib/utils/url'; diff --git a/src/routes/WelcomeScreen.svelte b/src/routes/WelcomeScreen.svelte index f9273c6f..f76ed5a9 100644 --- a/src/routes/WelcomeScreen.svelte +++ b/src/routes/WelcomeScreen.svelte @@ -6,10 +6,10 @@ /* eslint-disable svelte/no-navigation-without-resolve -- only contains external URLs */ import { asset } from '$app/paths'; import { PUBLIC_DISCORD_INVITE_URL, PUBLIC_GITHUB_PROJECT_URL } from '$env/static/public'; - import DiscordLogo from '$lib/components/svg/DiscordLogo.svelte'; - import GithubIcon from '$lib/components/svg/GithubIcon.svelte'; - import DotGrid from '$lib/components/DotGrid.svelte'; - import { Button } from '$lib/components/ui/button'; + import DiscordLogo from '$core/components/svg/DiscordLogo.svelte'; + import GithubIcon from '$core/components/svg/GithubIcon.svelte'; + import DotGrid from '$core/components/DotGrid.svelte'; + import { Button } from '$hadcn/button'; import { markWelcomed, markTourCompleted, diff --git a/src/routes/report/api-tokens/+page.svelte b/src/routes/report/api-tokens/+page.svelte index 01a27422..4385aa3d 100644 --- a/src/routes/report/api-tokens/+page.svelte +++ b/src/routes/report/api-tokens/+page.svelte @@ -9,13 +9,13 @@ import OctagonAlert from '@lucide/svelte/icons/octagon-alert'; import { goto } from '$app/navigation'; import { resolve } from '$app/paths'; - import Container from '$lib/components/Container.svelte'; + import Container from '$core/components/Container.svelte'; import Turnstile from '$lib/components/Turnstile.svelte'; - import { Button } from '$lib/components/ui/button'; - import * as Card from '$lib/components/ui/card'; - import { Checkbox } from '$lib/components/ui/checkbox'; - import { Label } from '$lib/components/ui/label'; - import ScrollArea from '$lib/components/ui/scroll-area/scroll-area.svelte'; + import { Button } from '$hadcn/button'; + import * as Card from '$hadcn/card'; + import { Checkbox } from '$hadcn/checkbox'; + import { Label } from '$hadcn/label'; + import ScrollArea from '$hadcn/scroll-area/scroll-area.svelte'; import { handleApiError } from '$lib/errorhandling/apiErrorHandling'; import { registerBreadcrumbs } from '$lib/state/breadcrumbs-state.svelte'; import { toast } from 'svelte-sonner'; diff --git a/src/routes/shares/public/[shareId=guid]/+page.svelte b/src/routes/shares/public/[shareId=guid]/+page.svelte index 7b12abfb..16ff8b69 100644 --- a/src/routes/shares/public/[shareId=guid]/+page.svelte +++ b/src/routes/shares/public/[shareId=guid]/+page.svelte @@ -4,9 +4,9 @@ import { CircleUser, LogIn, Undo2 } from '@lucide/svelte'; import { resolve } from '$app/paths'; import { page } from '$app/state'; - import { Button } from '$lib/components/ui/button'; - import * as Card from '$lib/components/ui/card/index.js'; - import Input from '$lib/components/ui/input/input.svelte'; + import { Button } from '$hadcn/button'; + import * as Card from '$hadcn/card'; + import Input from '$hadcn/input/input.svelte'; import { handleApiError } from '$lib/errorhandling/apiErrorHandling'; import { registerBreadcrumbs } from '$lib/state/breadcrumbs-state.svelte'; import { userState } from '$lib/state/user-state.svelte'; diff --git a/src/routes/shares/public/[shareId=guid]/ControlView.svelte b/src/routes/shares/public/[shareId=guid]/ControlView.svelte index 77e05ca0..f82c5d4c 100644 --- a/src/routes/shares/public/[shareId=guid]/ControlView.svelte +++ b/src/routes/shares/public/[shareId=guid]/ControlView.svelte @@ -6,8 +6,8 @@ import LiveControlModule from '$lib/components/ControlModules/LiveControlModule.svelte'; import ShockerCard from '$lib/components/ControlModules/ShockerCard.svelte'; import { getPauseReason } from '$lib/utils'; - import * as Avatar from '$lib/components/ui/avatar'; - import * as Tooltip from '$lib/components/ui/tooltip/index.js'; + import * as Avatar from '$hadcn/avatar'; + import * as Tooltip from '$hadcn/tooltip'; import { ShareLinkSignalr } from '$lib/signalr/sharelink.svelte'; import type { Control } from '$lib/signalr/models/Control'; import { ControlType } from '$lib/signalr/models/ControlType'; @@ -19,9 +19,9 @@ } from '$lib/state/live-control-state.svelte'; import { onMount, untrack } from 'svelte'; import { page } from '$app/state'; - import CopyInput from '$lib/components/CopyInput.svelte'; + import CopyInput from '$core/components/CopyInput.svelte'; import { getSiteShortURL } from '$lib/utils/url'; - import { Button } from '$lib/components/ui/button'; + import { Button } from '$hadcn/button'; import { Pencil } from '@lucide/svelte'; import { userState } from '$lib/state/user-state.svelte'; import { resolve } from '$app/paths'; diff --git a/src/routes/terminal/+page.svelte b/src/routes/terminal/+page.svelte index 182b7df7..7714cfa9 100644 --- a/src/routes/terminal/+page.svelte +++ b/src/routes/terminal/+page.svelte @@ -9,17 +9,17 @@ } from '@lucide/svelte'; import { browser } from '$app/environment'; import type { FirmwareChannel } from '$lib/api/firmwareCDN'; - import Container from '$lib/components/Container.svelte'; + import Container from '$core/components/Container.svelte'; import FirmwareChannelSelector from '$lib/components/FirmwareChannelSelector.svelte'; - import ChromeLogo from '$lib/components/svg/ChromeLogo.svelte'; - import EdgeLogo from '$lib/components/svg/EdgeLogo.svelte'; - import OperaLogo from '$lib/components/svg/OperaLogo.svelte'; - import { Button } from '$lib/components/ui/button'; - import * as Card from '$lib/components/ui/card'; - import { Checkbox } from '$lib/components/ui/checkbox'; - import * as Dialog from '$lib/components/ui/dialog'; - import { Label } from '$lib/components/ui/label'; - import { Progress } from '$lib/components/ui/progress'; + import ChromeLogo from '$core/components/svg/ChromeLogo.svelte'; + import EdgeLogo from '$core/components/svg/EdgeLogo.svelte'; + import OperaLogo from '$core/components/svg/OperaLogo.svelte'; + import { Button } from '$hadcn/button'; + import * as Card from '$hadcn/card'; + import { Checkbox } from '$hadcn/checkbox'; + import * as Dialog from '$hadcn/dialog'; + import { Label } from '$hadcn/label'; + import { Progress } from '$hadcn/progress'; import { useSerial } from '$lib/utils/serial-context.svelte'; import { getBrowserName } from '$lib/utils/compatibility'; import DeviceConfigurator from './DeviceConfigurator.svelte'; diff --git a/src/routes/terminal/DeviceConfigurator.svelte b/src/routes/terminal/DeviceConfigurator.svelte index 81e231d1..3e898752 100644 --- a/src/routes/terminal/DeviceConfigurator.svelte +++ b/src/routes/terminal/DeviceConfigurator.svelte @@ -1,13 +1,13 @@ diff --git a/src/routes/Footer.svelte b/src/routes/Footer.svelte index 521219f8..fa1db6ac 100644 --- a/src/routes/Footer.svelte +++ b/src/routes/Footer.svelte @@ -5,8 +5,8 @@ import { PUBLIC_GITHUB_PROJECT_URL } from '$env/static/public'; import { getConnectionState } from '$lib/signalr/user.svelte'; import { Wifi, WifiOff } from '@lucide/svelte'; - import * as DropdownMenu from '$hadcn/dropdown-menu'; - import { Button } from '$hadcn/button'; + import * as DropdownMenu from '@openshock/svelte-core/ui/dropdown-menu'; + import { Button } from '@openshock/svelte-core/ui/button'; import { backendMetadata } from '$lib/state/backend-metadata-state.svelte'; diff --git a/src/routes/Header.svelte b/src/routes/Header.svelte index a52e8f58..47d390a9 100644 --- a/src/routes/Header.svelte +++ b/src/routes/Header.svelte @@ -5,20 +5,20 @@ import { goto } from '$app/navigation'; import type { Pathname } from '$app/types'; import { PUBLIC_DISCORD_INVITE_URL, PUBLIC_GITHUB_PROJECT_URL } from '$env/static/public'; - import LightSwitch from '$core/components/LightSwitch.svelte'; - import DiscordLogo from '$core/components/svg/DiscordLogo.svelte'; - import GithubIcon from '$core/components/svg/GithubIcon.svelte'; - import { Button } from '$hadcn/button'; - import * as DropdownMenu from '$hadcn/dropdown-menu'; - import { Separator } from '$hadcn/separator'; - import { useSidebar } from '$hadcn/sidebar'; + import { LightSwitch } from '@openshock/svelte-core/components'; + import { DiscordLogo } from '@openshock/svelte-core/components/svg'; + import { GithubIcon } from '@openshock/svelte-core/components/svg'; + import { Button } from '@openshock/svelte-core/ui/button'; + import * as DropdownMenu from '@openshock/svelte-core/ui/dropdown-menu'; + import { Separator } from '@openshock/svelte-core/ui/separator'; + import { useSidebar } from '@openshock/svelte-core/ui/sidebar'; import { userState } from '$lib/state/user-state.svelte'; - import { cn } from '$core/utils/shadcn'; + import { cn } from '@openshock/svelte-core/utils/shadcn'; import Breadcrumb from './Breadcrumb.svelte'; import { prefixBase } from '$lib/utils/url'; import { resolve } from '$app/paths'; import { LogIn, UserPlus } from '@lucide/svelte'; - import { Spinner } from '$hadcn/spinner'; + import { Spinner } from '@openshock/svelte-core/ui/spinner'; let sidebar = useSidebar(); diff --git a/src/routes/Sidebar.svelte b/src/routes/Sidebar.svelte index 5ff95c27..ca869317 100644 --- a/src/routes/Sidebar.svelte +++ b/src/routes/Sidebar.svelte @@ -34,9 +34,9 @@ MenuSubButton, Root, useSidebar, - } from '$hadcn/sidebar'; + } from '@openshock/svelte-core/ui/sidebar'; import { userState } from '$lib/state/user-state.svelte'; - import type { AnyComponent } from '$core/types/AnyComponent'; + import type { AnyComponent } from '@openshock/svelte-core/types/AnyComponent'; import { isSerialSupported } from '$lib/utils/compatibility'; import { Collapsible } from 'bits-ui'; import { prefixBase } from '$lib/utils/url'; diff --git a/src/routes/WelcomeScreen.svelte b/src/routes/WelcomeScreen.svelte index f76ed5a9..012ca94d 100644 --- a/src/routes/WelcomeScreen.svelte +++ b/src/routes/WelcomeScreen.svelte @@ -6,10 +6,10 @@ /* eslint-disable svelte/no-navigation-without-resolve -- only contains external URLs */ import { asset } from '$app/paths'; import { PUBLIC_DISCORD_INVITE_URL, PUBLIC_GITHUB_PROJECT_URL } from '$env/static/public'; - import DiscordLogo from '$core/components/svg/DiscordLogo.svelte'; - import GithubIcon from '$core/components/svg/GithubIcon.svelte'; - import DotGrid from '$core/components/DotGrid.svelte'; - import { Button } from '$hadcn/button'; + import { DiscordLogo } from '@openshock/svelte-core/components/svg'; + import { GithubIcon } from '@openshock/svelte-core/components/svg'; + import { DotGrid } from '@openshock/svelte-core/components'; + import { Button } from '@openshock/svelte-core/ui/button'; import { markWelcomed, markTourCompleted, diff --git a/src/routes/report/api-tokens/+page.svelte b/src/routes/report/api-tokens/+page.svelte index 4385aa3d..b50c4c5b 100644 --- a/src/routes/report/api-tokens/+page.svelte +++ b/src/routes/report/api-tokens/+page.svelte @@ -9,13 +9,13 @@ import OctagonAlert from '@lucide/svelte/icons/octagon-alert'; import { goto } from '$app/navigation'; import { resolve } from '$app/paths'; - import Container from '$core/components/Container.svelte'; + import { Container } from '@openshock/svelte-core/components'; import Turnstile from '$lib/components/Turnstile.svelte'; - import { Button } from '$hadcn/button'; - import * as Card from '$hadcn/card'; - import { Checkbox } from '$hadcn/checkbox'; - import { Label } from '$hadcn/label'; - import ScrollArea from '$hadcn/scroll-area/scroll-area.svelte'; + import { Button } from '@openshock/svelte-core/ui/button'; + import * as Card from '@openshock/svelte-core/ui/card'; + import { Checkbox } from '@openshock/svelte-core/ui/checkbox'; + import { Label } from '@openshock/svelte-core/ui/label'; + import { ScrollArea } from '@openshock/svelte-core/ui/scroll-area'; import { handleApiError } from '$lib/errorhandling/apiErrorHandling'; import { registerBreadcrumbs } from '$lib/state/breadcrumbs-state.svelte'; import { toast } from 'svelte-sonner'; diff --git a/src/routes/shares/public/[shareId=guid]/+page.svelte b/src/routes/shares/public/[shareId=guid]/+page.svelte index 16ff8b69..c243d620 100644 --- a/src/routes/shares/public/[shareId=guid]/+page.svelte +++ b/src/routes/shares/public/[shareId=guid]/+page.svelte @@ -4,9 +4,9 @@ import { CircleUser, LogIn, Undo2 } from '@lucide/svelte'; import { resolve } from '$app/paths'; import { page } from '$app/state'; - import { Button } from '$hadcn/button'; - import * as Card from '$hadcn/card'; - import Input from '$hadcn/input/input.svelte'; + import { Button } from '@openshock/svelte-core/ui/button'; + import * as Card from '@openshock/svelte-core/ui/card'; + import { Input } from '@openshock/svelte-core/ui/input'; import { handleApiError } from '$lib/errorhandling/apiErrorHandling'; import { registerBreadcrumbs } from '$lib/state/breadcrumbs-state.svelte'; import { userState } from '$lib/state/user-state.svelte'; diff --git a/src/routes/shares/public/[shareId=guid]/ControlView.svelte b/src/routes/shares/public/[shareId=guid]/ControlView.svelte index f82c5d4c..2a5aacd5 100644 --- a/src/routes/shares/public/[shareId=guid]/ControlView.svelte +++ b/src/routes/shares/public/[shareId=guid]/ControlView.svelte @@ -6,8 +6,8 @@ import LiveControlModule from '$lib/components/ControlModules/LiveControlModule.svelte'; import ShockerCard from '$lib/components/ControlModules/ShockerCard.svelte'; import { getPauseReason } from '$lib/utils'; - import * as Avatar from '$hadcn/avatar'; - import * as Tooltip from '$hadcn/tooltip'; + import * as Avatar from '@openshock/svelte-core/ui/avatar'; + import * as Tooltip from '@openshock/svelte-core/ui/tooltip'; import { ShareLinkSignalr } from '$lib/signalr/sharelink.svelte'; import type { Control } from '$lib/signalr/models/Control'; import { ControlType } from '$lib/signalr/models/ControlType'; @@ -19,9 +19,9 @@ } from '$lib/state/live-control-state.svelte'; import { onMount, untrack } from 'svelte'; import { page } from '$app/state'; - import CopyInput from '$core/components/CopyInput.svelte'; + import { CopyInput } from '@openshock/svelte-core/components'; import { getSiteShortURL } from '$lib/utils/url'; - import { Button } from '$hadcn/button'; + import { Button } from '@openshock/svelte-core/ui/button'; import { Pencil } from '@lucide/svelte'; import { userState } from '$lib/state/user-state.svelte'; import { resolve } from '$app/paths'; diff --git a/src/routes/terminal/+page.svelte b/src/routes/terminal/+page.svelte index 7714cfa9..0ba06d64 100644 --- a/src/routes/terminal/+page.svelte +++ b/src/routes/terminal/+page.svelte @@ -9,17 +9,17 @@ } from '@lucide/svelte'; import { browser } from '$app/environment'; import type { FirmwareChannel } from '$lib/api/firmwareCDN'; - import Container from '$core/components/Container.svelte'; + import { Container } from '@openshock/svelte-core/components'; import FirmwareChannelSelector from '$lib/components/FirmwareChannelSelector.svelte'; - import ChromeLogo from '$core/components/svg/ChromeLogo.svelte'; - import EdgeLogo from '$core/components/svg/EdgeLogo.svelte'; - import OperaLogo from '$core/components/svg/OperaLogo.svelte'; - import { Button } from '$hadcn/button'; - import * as Card from '$hadcn/card'; - import { Checkbox } from '$hadcn/checkbox'; - import * as Dialog from '$hadcn/dialog'; - import { Label } from '$hadcn/label'; - import { Progress } from '$hadcn/progress'; + import { ChromeLogo } from '@openshock/svelte-core/components/svg'; + import { EdgeLogo } from '@openshock/svelte-core/components/svg'; + import { OperaLogo } from '@openshock/svelte-core/components/svg'; + import { Button } from '@openshock/svelte-core/ui/button'; + import * as Card from '@openshock/svelte-core/ui/card'; + import { Checkbox } from '@openshock/svelte-core/ui/checkbox'; + import * as Dialog from '@openshock/svelte-core/ui/dialog'; + import { Label } from '@openshock/svelte-core/ui/label'; + import { Progress } from '@openshock/svelte-core/ui/progress'; import { useSerial } from '$lib/utils/serial-context.svelte'; import { getBrowserName } from '$lib/utils/compatibility'; import DeviceConfigurator from './DeviceConfigurator.svelte'; diff --git a/src/routes/terminal/DeviceConfigurator.svelte b/src/routes/terminal/DeviceConfigurator.svelte index 3e898752..1c616267 100644 --- a/src/routes/terminal/DeviceConfigurator.svelte +++ b/src/routes/terminal/DeviceConfigurator.svelte @@ -1,13 +1,13 @@