@happyvertical/smrt-ui 0.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +50 -0
- package/CLAUDE.md +1 -0
- package/LICENSE +7 -0
- package/dist/actions/__tests__/ripple.test.js +28 -0
- package/dist/actions/permission.d.ts +34 -0
- package/dist/actions/permission.d.ts.map +1 -0
- package/dist/actions/permission.js +70 -0
- package/dist/actions/ripple.d.ts +7 -0
- package/dist/actions/ripple.d.ts.map +1 -0
- package/dist/actions/ripple.js +65 -0
- package/dist/components/calendar/Calendar.svelte +520 -0
- package/dist/components/calendar/Calendar.svelte.d.ts +17 -0
- package/dist/components/calendar/Calendar.svelte.d.ts.map +1 -0
- package/dist/components/calendar/DayView.svelte +389 -0
- package/dist/components/calendar/DayView.svelte.d.ts +13 -0
- package/dist/components/calendar/DayView.svelte.d.ts.map +1 -0
- package/dist/components/calendar/index.d.ts +6 -0
- package/dist/components/calendar/index.d.ts.map +1 -0
- package/dist/components/calendar/index.js +5 -0
- package/dist/components/chat/MessageBubble.svelte +126 -0
- package/dist/components/chat/MessageBubble.svelte.d.ts +30 -0
- package/dist/components/chat/MessageBubble.svelte.d.ts.map +1 -0
- package/dist/components/chat/ReactionPicker.svelte +89 -0
- package/dist/components/chat/ReactionPicker.svelte.d.ts +19 -0
- package/dist/components/chat/ReactionPicker.svelte.d.ts.map +1 -0
- package/dist/components/chat/TypingIndicator.svelte +90 -0
- package/dist/components/chat/TypingIndicator.svelte.d.ts +17 -0
- package/dist/components/chat/TypingIndicator.svelte.d.ts.map +1 -0
- package/dist/components/chat/__tests__/chat-primitives.test.js +67 -0
- package/dist/components/chat/index.d.ts +10 -0
- package/dist/components/chat/index.d.ts.map +1 -0
- package/dist/components/chat/index.js +9 -0
- package/dist/components/data/DataTable.svelte +519 -0
- package/dist/components/data/DataTable.svelte.d.ts +49 -0
- package/dist/components/data/DataTable.svelte.d.ts.map +1 -0
- package/dist/components/data/__tests__/DataTable.test.js +48 -0
- package/dist/components/data/__tests__/data-table-helpers.test.js +36 -0
- package/dist/components/data/index.d.ts +6 -0
- package/dist/components/data/index.d.ts.map +1 -0
- package/dist/components/data/index.js +5 -0
- package/dist/components/data/types.d.ts +104 -0
- package/dist/components/data/types.d.ts.map +1 -0
- package/dist/components/data/types.js +45 -0
- package/dist/components/display/ConfidenceBadge.svelte +142 -0
- package/dist/components/display/ConfidenceBadge.svelte.d.ts +25 -0
- package/dist/components/display/ConfidenceBadge.svelte.d.ts.map +1 -0
- package/dist/components/display/CurrencyDisplay.svelte +106 -0
- package/dist/components/display/CurrencyDisplay.svelte.d.ts +30 -0
- package/dist/components/display/CurrencyDisplay.svelte.d.ts.map +1 -0
- package/dist/components/display/DateDisplay.svelte +122 -0
- package/dist/components/display/DateDisplay.svelte.d.ts +24 -0
- package/dist/components/display/DateDisplay.svelte.d.ts.map +1 -0
- package/dist/components/display/Icon.svelte +77 -0
- package/dist/components/display/Icon.svelte.d.ts +28 -0
- package/dist/components/display/Icon.svelte.d.ts.map +1 -0
- package/dist/components/display/StatusBadge.svelte +256 -0
- package/dist/components/display/StatusBadge.svelte.d.ts +24 -0
- package/dist/components/display/StatusBadge.svelte.d.ts.map +1 -0
- package/dist/components/display/__tests__/ConfidenceBadge.test.js +96 -0
- package/dist/components/display/__tests__/CurrencyDisplay.test.js +114 -0
- package/dist/components/display/__tests__/DateDisplay.test.js +114 -0
- package/dist/components/display/__tests__/Icon.test.js +93 -0
- package/dist/components/display/__tests__/StatusBadge.test.js +98 -0
- package/dist/components/display/index.d.ts +10 -0
- package/dist/components/display/index.d.ts.map +1 -0
- package/dist/components/display/index.js +9 -0
- package/dist/components/display/types.d.ts +5 -0
- package/dist/components/display/types.d.ts.map +1 -0
- package/dist/components/display/types.js +4 -0
- package/dist/components/feedback/ConfirmDialog.svelte +226 -0
- package/dist/components/feedback/ConfirmDialog.svelte.d.ts +25 -0
- package/dist/components/feedback/ConfirmDialog.svelte.d.ts.map +1 -0
- package/dist/components/feedback/LoadingOverlay.svelte +281 -0
- package/dist/components/feedback/LoadingOverlay.svelte.d.ts +31 -0
- package/dist/components/feedback/LoadingOverlay.svelte.d.ts.map +1 -0
- package/dist/components/feedback/Modal.svelte +393 -0
- package/dist/components/feedback/Modal.svelte.d.ts +46 -0
- package/dist/components/feedback/Modal.svelte.d.ts.map +1 -0
- package/dist/components/feedback/ProgressBar.svelte +162 -0
- package/dist/components/feedback/ProgressBar.svelte.d.ts +21 -0
- package/dist/components/feedback/ProgressBar.svelte.d.ts.map +1 -0
- package/dist/components/feedback/__tests__/ConfirmDialog.test.js +111 -0
- package/dist/components/feedback/__tests__/LoadingOverlay.test.js +99 -0
- package/dist/components/feedback/__tests__/Modal.test.js +72 -0
- package/dist/components/feedback/__tests__/ProgressBar.test.js +89 -0
- package/dist/components/feedback/index.d.ts +8 -0
- package/dist/components/feedback/index.d.ts.map +1 -0
- package/dist/components/feedback/index.js +10 -0
- package/dist/components/layout/Container.svelte +53 -0
- package/dist/components/layout/Container.svelte.d.ts +11 -0
- package/dist/components/layout/Container.svelte.d.ts.map +1 -0
- package/dist/components/layout/EmptyState.svelte +187 -0
- package/dist/components/layout/EmptyState.svelte.d.ts +28 -0
- package/dist/components/layout/EmptyState.svelte.d.ts.map +1 -0
- package/dist/components/layout/Footer.svelte +63 -0
- package/dist/components/layout/Footer.svelte.d.ts +8 -0
- package/dist/components/layout/Footer.svelte.d.ts.map +1 -0
- package/dist/components/layout/Grid.svelte +241 -0
- package/dist/components/layout/Grid.svelte.d.ts +56 -0
- package/dist/components/layout/Grid.svelte.d.ts.map +1 -0
- package/dist/components/layout/Header.svelte +86 -0
- package/dist/components/layout/Header.svelte.d.ts +9 -0
- package/dist/components/layout/Header.svelte.d.ts.map +1 -0
- package/dist/components/layout/Masthead.svelte +219 -0
- package/dist/components/layout/Masthead.svelte.d.ts +13 -0
- package/dist/components/layout/Masthead.svelte.d.ts.map +1 -0
- package/dist/components/layout/PageHeader.svelte +131 -0
- package/dist/components/layout/PageHeader.svelte.d.ts +26 -0
- package/dist/components/layout/PageHeader.svelte.d.ts.map +1 -0
- package/dist/components/layout/SummaryCard.svelte +203 -0
- package/dist/components/layout/SummaryCard.svelte.d.ts +20 -0
- package/dist/components/layout/SummaryCard.svelte.d.ts.map +1 -0
- package/dist/components/layout/__tests__/Container.test.js +62 -0
- package/dist/components/layout/__tests__/EmptyState.test.js +83 -0
- package/dist/components/layout/__tests__/Footer.test.js +50 -0
- package/dist/components/layout/__tests__/Grid.test.js +121 -0
- package/dist/components/layout/__tests__/Header.test.js +48 -0
- package/dist/components/layout/__tests__/Masthead.test.js +93 -0
- package/dist/components/layout/__tests__/PageHeader.test.js +80 -0
- package/dist/components/layout/__tests__/SummaryCard.test.js +82 -0
- package/dist/components/layout/index.d.ts +12 -0
- package/dist/components/layout/index.d.ts.map +1 -0
- package/dist/components/layout/index.js +11 -0
- package/dist/components/memberships/MembershipCard.svelte +163 -0
- package/dist/components/memberships/MembershipCard.svelte.d.ts +12 -0
- package/dist/components/memberships/MembershipCard.svelte.d.ts.map +1 -0
- package/dist/components/memberships/MembershipList.svelte +98 -0
- package/dist/components/memberships/MembershipList.svelte.d.ts +19 -0
- package/dist/components/memberships/MembershipList.svelte.d.ts.map +1 -0
- package/dist/components/nav/FilterChips.svelte +152 -0
- package/dist/components/nav/FilterChips.svelte.d.ts +19 -0
- package/dist/components/nav/FilterChips.svelte.d.ts.map +1 -0
- package/dist/components/nav/Tabs.svelte +252 -0
- package/dist/components/nav/Tabs.svelte.d.ts +34 -0
- package/dist/components/nav/Tabs.svelte.d.ts.map +1 -0
- package/dist/components/nav/__tests__/FilterChips.test.js +94 -0
- package/dist/components/nav/__tests__/Tabs.test.js +128 -0
- package/dist/components/nav/index.d.ts +7 -0
- package/dist/components/nav/index.d.ts.map +1 -0
- package/dist/components/nav/index.js +6 -0
- package/dist/components/nav/types.d.ts +24 -0
- package/dist/components/nav/types.d.ts.map +1 -0
- package/dist/components/nav/types.js +4 -0
- package/dist/components/permissions/PermissionCheck.svelte +45 -0
- package/dist/components/permissions/PermissionCheck.svelte.d.ts +19 -0
- package/dist/components/permissions/PermissionCheck.svelte.d.ts.map +1 -0
- package/dist/components/roles/RoleBadge.svelte +84 -0
- package/dist/components/roles/RoleBadge.svelte.d.ts +13 -0
- package/dist/components/roles/RoleBadge.svelte.d.ts.map +1 -0
- package/dist/components/roles/RoleSelector.svelte +216 -0
- package/dist/components/roles/RoleSelector.svelte.d.ts +13 -0
- package/dist/components/roles/RoleSelector.svelte.d.ts.map +1 -0
- package/dist/components/theme/ThemeProvider.svelte +71 -0
- package/dist/components/theme/ThemeProvider.svelte.d.ts +10 -0
- package/dist/components/theme/ThemeProvider.svelte.d.ts.map +1 -0
- package/dist/components/theme/context.svelte.d.ts +15 -0
- package/dist/components/theme/context.svelte.d.ts.map +1 -0
- package/dist/components/theme/context.svelte.js +42 -0
- package/dist/components/theme/index.d.ts +3 -0
- package/dist/components/theme/index.d.ts.map +1 -0
- package/dist/components/theme/index.js +2 -0
- package/dist/components/ui/Avatar.svelte +167 -0
- package/dist/components/ui/Avatar.svelte.d.ts +26 -0
- package/dist/components/ui/Avatar.svelte.d.ts.map +1 -0
- package/dist/components/ui/Badge.svelte +70 -0
- package/dist/components/ui/Badge.svelte.d.ts +12 -0
- package/dist/components/ui/Badge.svelte.d.ts.map +1 -0
- package/dist/components/ui/Button.svelte +226 -0
- package/dist/components/ui/Button.svelte.d.ts +28 -0
- package/dist/components/ui/Button.svelte.d.ts.map +1 -0
- package/dist/components/ui/Card.svelte +122 -0
- package/dist/components/ui/Card.svelte.d.ts +15 -0
- package/dist/components/ui/Card.svelte.d.ts.map +1 -0
- package/dist/components/ui/Chip.svelte +167 -0
- package/dist/components/ui/Chip.svelte.d.ts +33 -0
- package/dist/components/ui/Chip.svelte.d.ts.map +1 -0
- package/dist/components/ui/Dropdown.svelte +250 -0
- package/dist/components/ui/Dropdown.svelte.d.ts +20 -0
- package/dist/components/ui/Dropdown.svelte.d.ts.map +1 -0
- package/dist/components/ui/Pagination.svelte +294 -0
- package/dist/components/ui/Pagination.svelte.d.ts +21 -0
- package/dist/components/ui/Pagination.svelte.d.ts.map +1 -0
- package/dist/components/ui/Skeleton.svelte +113 -0
- package/dist/components/ui/Skeleton.svelte.d.ts +24 -0
- package/dist/components/ui/Skeleton.svelte.d.ts.map +1 -0
- package/dist/components/ui/Tooltip.svelte +120 -0
- package/dist/components/ui/Tooltip.svelte.d.ts +24 -0
- package/dist/components/ui/Tooltip.svelte.d.ts.map +1 -0
- package/dist/components/ui/Tree.svelte +209 -0
- package/dist/components/ui/Tree.svelte.d.ts +17 -0
- package/dist/components/ui/Tree.svelte.d.ts.map +1 -0
- package/dist/components/ui/__tests__/Badge.test.js +76 -0
- package/dist/components/ui/__tests__/Button.test.js +69 -0
- package/dist/components/ui/__tests__/Card.test.js +103 -0
- package/dist/components/ui/__tests__/Pagination.test.js +99 -0
- package/dist/components/ui/__tests__/gap-primitives-interactive.test.js +112 -0
- package/dist/components/ui/__tests__/gap-primitives.test.js +84 -0
- package/dist/components/ui/index.d.ts +14 -0
- package/dist/components/ui/index.d.ts.map +1 -0
- package/dist/components/ui/index.js +18 -0
- package/dist/i18n/Trans.svelte +29 -0
- package/dist/i18n/Trans.svelte.d.ts +24 -0
- package/dist/i18n/Trans.svelte.d.ts.map +1 -0
- package/dist/i18n/__tests__/i18n.test.js +74 -0
- package/dist/i18n/__tests__/render-parity.spec.js +37 -0
- package/dist/i18n/context.svelte.d.ts +43 -0
- package/dist/i18n/context.svelte.d.ts.map +1 -0
- package/dist/i18n/context.svelte.js +69 -0
- package/dist/i18n/index.d.ts +17 -0
- package/dist/i18n/index.d.ts.map +1 -0
- package/dist/i18n/index.js +24 -0
- package/dist/i18n/registry.d.ts +44 -0
- package/dist/i18n/registry.d.ts.map +1 -0
- package/dist/i18n/registry.js +60 -0
- package/dist/i18n/render.d.ts +22 -0
- package/dist/i18n/render.d.ts.map +1 -0
- package/dist/i18n/render.js +44 -0
- package/dist/i18n/strings.d.ts +7 -0
- package/dist/i18n/strings.d.ts.map +1 -0
- package/dist/i18n/strings.js +19 -0
- package/dist/i18n/strings.ui.d.ts +34 -0
- package/dist/i18n/strings.ui.d.ts.map +1 -0
- package/dist/i18n/strings.ui.js +44 -0
- package/dist/i18n/use-i18n.d.ts +20 -0
- package/dist/i18n/use-i18n.d.ts.map +1 -0
- package/dist/i18n/use-i18n.js +21 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +38 -0
- package/dist/registry/index.d.ts +6 -0
- package/dist/registry/index.d.ts.map +1 -0
- package/dist/registry/index.js +4 -0
- package/dist/registry/module-registry.d.ts +58 -0
- package/dist/registry/module-registry.d.ts.map +1 -0
- package/dist/registry/module-registry.js +94 -0
- package/dist/styles/index.d.ts +4 -0
- package/dist/styles/index.d.ts.map +1 -0
- package/dist/styles/index.js +6 -0
- package/dist/styles/tokens.css +76 -0
- package/dist/test-support/a11y.d.ts +16 -0
- package/dist/test-support/a11y.d.ts.map +1 -0
- package/dist/test-support/a11y.js +32 -0
- package/dist/test-support/setup.d.ts +11 -0
- package/dist/test-support/setup.d.ts.map +1 -0
- package/dist/test-support/setup.js +33 -0
- package/dist/theme/ThemeProvider.svelte +207 -0
- package/dist/theme/ThemeProvider.svelte.d.ts +22 -0
- package/dist/theme/ThemeProvider.svelte.d.ts.map +1 -0
- package/dist/theme/context.d.ts +49 -0
- package/dist/theme/context.d.ts.map +1 -0
- package/dist/theme/context.js +32 -0
- package/dist/theme/index.d.ts +7 -0
- package/dist/theme/index.d.ts.map +1 -0
- package/dist/theme/index.js +9 -0
- package/dist/theme/tokens.d.ts +309 -0
- package/dist/theme/tokens.d.ts.map +1 -0
- package/dist/theme/tokens.js +418 -0
- package/dist/themes/CUSTOM_THEME_GUIDE.md +341 -0
- package/dist/themes/README.md +675 -0
- package/dist/themes/ThemeProvider.svelte +275 -0
- package/dist/themes/ThemeProvider.svelte.d.ts +24 -0
- package/dist/themes/ThemeProvider.svelte.d.ts.map +1 -0
- package/dist/themes/__tests__/css-generator.test.js +32 -0
- package/dist/themes/__tests__/registry.test.js +43 -0
- package/dist/themes/__tests__/token-aliases.test.js +176 -0
- package/dist/themes/components/ColorSchemeToggle.svelte +205 -0
- package/dist/themes/components/ColorSchemeToggle.svelte.d.ts +14 -0
- package/dist/themes/components/ColorSchemeToggle.svelte.d.ts.map +1 -0
- package/dist/themes/components/ThemeSwitcher.svelte +188 -0
- package/dist/themes/components/ThemeSwitcher.svelte.d.ts +14 -0
- package/dist/themes/components/ThemeSwitcher.svelte.d.ts.map +1 -0
- package/dist/themes/components/index.d.ts +8 -0
- package/dist/themes/components/index.d.ts.map +1 -0
- package/dist/themes/components/index.js +7 -0
- package/dist/themes/context.svelte.d.ts +30 -0
- package/dist/themes/context.svelte.d.ts.map +1 -0
- package/dist/themes/context.svelte.js +42 -0
- package/dist/themes/create-theme.d.ts +99 -0
- package/dist/themes/create-theme.d.ts.map +1 -0
- package/dist/themes/create-theme.js +389 -0
- package/dist/themes/css-generator.d.ts +44 -0
- package/dist/themes/css-generator.d.ts.map +1 -0
- package/dist/themes/css-generator.js +226 -0
- package/dist/themes/glass/index.d.ts +14 -0
- package/dist/themes/glass/index.d.ts.map +1 -0
- package/dist/themes/glass/index.js +286 -0
- package/dist/themes/index.d.ts +31 -0
- package/dist/themes/index.d.ts.map +1 -0
- package/dist/themes/index.js +37 -0
- package/dist/themes/material/index.d.ts +13 -0
- package/dist/themes/material/index.d.ts.map +1 -0
- package/dist/themes/material/index.js +269 -0
- package/dist/themes/registry.d.ts +64 -0
- package/dist/themes/registry.d.ts.map +1 -0
- package/dist/themes/registry.js +122 -0
- package/dist/themes/shared.d.ts +78 -0
- package/dist/themes/shared.d.ts.map +1 -0
- package/dist/themes/shared.js +179 -0
- package/dist/themes/studio/index.d.ts +14 -0
- package/dist/themes/studio/index.d.ts.map +1 -0
- package/dist/themes/studio/index.js +270 -0
- package/dist/themes/styles/all.css +12 -0
- package/dist/themes/styles/glass.css +432 -0
- package/dist/themes/styles/index.d.ts +22 -0
- package/dist/themes/styles/index.d.ts.map +1 -0
- package/dist/themes/styles/index.js +23 -0
- package/dist/themes/styles/material.css +364 -0
- package/dist/themes/styles/studio.css +416 -0
- package/dist/themes/types.d.ts +273 -0
- package/dist/themes/types.d.ts.map +1 -0
- package/dist/themes/types.js +15 -0
- package/dist/types-generic.d.ts +75 -0
- package/dist/types-generic.d.ts.map +1 -0
- package/dist/types-generic.js +1 -0
- package/dist/utils/forms/__tests__/formatters.test.js +27 -0
- package/dist/utils/forms/formatters.d.ts +14 -0
- package/dist/utils/forms/formatters.d.ts.map +1 -0
- package/dist/utils/forms/formatters.js +77 -0
- package/dist/utils/import-optional.d.ts +5 -0
- package/dist/utils/import-optional.d.ts.map +1 -0
- package/dist/utils/import-optional.js +7 -0
- package/dist/utils/theme/__tests__/color.test.js +72 -0
- package/dist/utils/theme/__tests__/typography.test.js +11 -0
- package/dist/utils/theme/color.d.ts +70 -0
- package/dist/utils/theme/color.d.ts.map +1 -0
- package/dist/utils/theme/color.js +221 -0
- package/dist/utils/theme/typography.d.ts +27 -0
- package/dist/utils/theme/typography.d.ts.map +1 -0
- package/dist/utils/theme/typography.js +30 -0
- package/package.json +143 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified Theme System Types
|
|
3
|
+
*
|
|
4
|
+
* Core types for the multi-theme architecture supporting Material, Glass, and Studio themes.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Default theme configuration
|
|
8
|
+
*/
|
|
9
|
+
export const defaultThemeConfig = {
|
|
10
|
+
preset: 'material',
|
|
11
|
+
colorScheme: 'system',
|
|
12
|
+
borderRadius: 'md',
|
|
13
|
+
persist: true,
|
|
14
|
+
storageKey: 'smrt-theme',
|
|
15
|
+
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generic component types migrated from @happyvertical/svelte
|
|
3
|
+
*/
|
|
4
|
+
import type { Snippet } from 'svelte';
|
|
5
|
+
import type { HTMLAttributes, HTMLButtonAttributes } from 'svelte/elements';
|
|
6
|
+
export type BadgeVariant = 'default' | 'primary' | 'success' | 'warning' | 'error' | 'info';
|
|
7
|
+
export type BadgeSize = 'sm' | 'md';
|
|
8
|
+
export interface BadgeProps extends Omit<HTMLAttributes<HTMLSpanElement>, 'class'> {
|
|
9
|
+
variant?: BadgeVariant;
|
|
10
|
+
size?: BadgeSize;
|
|
11
|
+
children?: Snippet;
|
|
12
|
+
}
|
|
13
|
+
export type ButtonVariant = 'primary' | 'secondary' | 'ghost' | 'danger';
|
|
14
|
+
export type ButtonSize = 'sm' | 'md' | 'lg';
|
|
15
|
+
export interface ButtonProps extends Omit<HTMLButtonAttributes, 'class'> {
|
|
16
|
+
variant?: ButtonVariant;
|
|
17
|
+
size?: ButtonSize;
|
|
18
|
+
href?: string;
|
|
19
|
+
children?: Snippet;
|
|
20
|
+
}
|
|
21
|
+
export type CardVariant = 'default' | 'outlined' | 'elevated';
|
|
22
|
+
export type CardPadding = 'none' | 'sm' | 'md' | 'lg';
|
|
23
|
+
export interface CardProps extends Omit<HTMLAttributes<HTMLDivElement>, 'class'> {
|
|
24
|
+
variant?: CardVariant;
|
|
25
|
+
padding?: CardPadding;
|
|
26
|
+
hoverable?: boolean;
|
|
27
|
+
children?: Snippet;
|
|
28
|
+
header?: Snippet;
|
|
29
|
+
footer?: Snippet;
|
|
30
|
+
}
|
|
31
|
+
export type AvatarSize = 'sm' | 'md' | 'lg' | 'xl';
|
|
32
|
+
export type AvatarStatus = 'online' | 'offline' | 'away' | 'busy';
|
|
33
|
+
export type ChipSize = 'sm' | 'md';
|
|
34
|
+
export type SkeletonVariant = 'text' | 'circle' | 'rect';
|
|
35
|
+
export type TooltipPlacement = 'top' | 'bottom' | 'left' | 'right';
|
|
36
|
+
export type DropdownPlacement = 'bottom-start' | 'bottom-end' | 'top-start' | 'top-end';
|
|
37
|
+
/** An item in a `Dropdown`/`Menu`. */
|
|
38
|
+
export interface MenuItem {
|
|
39
|
+
/** Stable id, returned by `onselect`. */
|
|
40
|
+
id: string;
|
|
41
|
+
/** Visible item label. */
|
|
42
|
+
label: string;
|
|
43
|
+
/** Disable this item. */
|
|
44
|
+
disabled?: boolean;
|
|
45
|
+
/** Per-item activation handler. */
|
|
46
|
+
onselect?: () => void;
|
|
47
|
+
}
|
|
48
|
+
/** A node in a `Tree`. */
|
|
49
|
+
export interface TreeNode {
|
|
50
|
+
/** Stable id, returned by `onselect`. */
|
|
51
|
+
id: string;
|
|
52
|
+
/** Visible node label. */
|
|
53
|
+
label: string;
|
|
54
|
+
/** Child nodes; presence makes the node expandable. */
|
|
55
|
+
children?: TreeNode[];
|
|
56
|
+
}
|
|
57
|
+
export type ChatMessageRole = 'user' | 'agent' | 'system';
|
|
58
|
+
export interface DayEventDetail {
|
|
59
|
+
type: string;
|
|
60
|
+
name: string;
|
|
61
|
+
slug: string;
|
|
62
|
+
startTime: string;
|
|
63
|
+
venue?: string;
|
|
64
|
+
councilSlug?: string;
|
|
65
|
+
}
|
|
66
|
+
export interface DayEventsData {
|
|
67
|
+
date: string;
|
|
68
|
+
events: DayEventDetail[];
|
|
69
|
+
}
|
|
70
|
+
export interface DayForecast {
|
|
71
|
+
icon: string;
|
|
72
|
+
high: number;
|
|
73
|
+
low: number;
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=types-generic.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types-generic.d.ts","sourceRoot":"","sources":["../src/types-generic.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { formatEmail, formatText, matchOption, parseSpokenBoolean, } from '../formatters';
|
|
3
|
+
describe('Form Formatters', () => {
|
|
4
|
+
it('should format email correctly', () => {
|
|
5
|
+
expect(formatEmail('john at example dot com')).toBe('john@example.com');
|
|
6
|
+
expect(formatEmail('JOHN DOT DOE AT GMAIL DOT COM')).toBe('john.doe@gmail.com');
|
|
7
|
+
});
|
|
8
|
+
it('should format text correctly', () => {
|
|
9
|
+
expect(formatText('my name is John')).toBe('John');
|
|
10
|
+
expect(formatText('um so well hello')).toBe('hello');
|
|
11
|
+
});
|
|
12
|
+
it('should parse spoken boolean correctly', () => {
|
|
13
|
+
expect(parseSpokenBoolean('yes please')).toBe(true);
|
|
14
|
+
expect(parseSpokenBoolean('no way')).toBe(false);
|
|
15
|
+
expect(parseSpokenBoolean('maybe')).toBe(null);
|
|
16
|
+
});
|
|
17
|
+
it('should match options correctly', () => {
|
|
18
|
+
const options = [
|
|
19
|
+
{ label: 'Red', value: 'red' },
|
|
20
|
+
{ label: 'Green', value: 'green' },
|
|
21
|
+
{ label: 'Blue', value: 'blue' },
|
|
22
|
+
];
|
|
23
|
+
expect(matchOption('red', options)).toBe('red');
|
|
24
|
+
expect(matchOption('I want green', options)).toBe('green');
|
|
25
|
+
expect(matchOption('yellow', options)).toBe(null);
|
|
26
|
+
});
|
|
27
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare function formatEmail(transcript: string): string;
|
|
2
|
+
export declare function formatText(transcript: string): string;
|
|
3
|
+
/**
|
|
4
|
+
* Parses a spoken string into a boolean value.
|
|
5
|
+
*/
|
|
6
|
+
export declare function parseSpokenBoolean(text: string): boolean | null;
|
|
7
|
+
/**
|
|
8
|
+
* Matches a spoken string against a list of options.
|
|
9
|
+
*/
|
|
10
|
+
export declare function matchOption(spokenText: string, options: Array<{
|
|
11
|
+
label: string;
|
|
12
|
+
value: string;
|
|
13
|
+
}>): string | null;
|
|
14
|
+
//# sourceMappingURL=formatters.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatters.d.ts","sourceRoot":"","sources":["../../../src/utils/forms/formatters.ts"],"names":[],"mappings":"AAAA,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAStD;AAED,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAKrD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAsC/D;AAED;;GAEG;AACH,wBAAgB,WAAW,CACzB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,GAC/C,MAAM,GAAG,IAAI,CAwBf"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
export function formatEmail(transcript) {
|
|
2
|
+
return transcript
|
|
3
|
+
.toLowerCase()
|
|
4
|
+
.replace(/\s+at\s+/gi, '@')
|
|
5
|
+
.replace(/\bat\b/gi, '@')
|
|
6
|
+
.replace(/\s+dot\s+/gi, '.')
|
|
7
|
+
.replace(/\bdot\b/gi, '.')
|
|
8
|
+
.replace(/\s+/g, '')
|
|
9
|
+
.trim();
|
|
10
|
+
}
|
|
11
|
+
export function formatText(transcript) {
|
|
12
|
+
return transcript
|
|
13
|
+
.replace(/^(my name is|i am|i'm|it's|this is|the name is)\s*/i, '')
|
|
14
|
+
.replace(/\b(um|uh|like|so|well)\b\s*/gi, '')
|
|
15
|
+
.trim();
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Parses a spoken string into a boolean value.
|
|
19
|
+
*/
|
|
20
|
+
export function parseSpokenBoolean(text) {
|
|
21
|
+
const normalized = text.toLowerCase().trim();
|
|
22
|
+
const trueWords = [
|
|
23
|
+
'yes',
|
|
24
|
+
'yeah',
|
|
25
|
+
'yep',
|
|
26
|
+
'true',
|
|
27
|
+
'correct',
|
|
28
|
+
'affirmative',
|
|
29
|
+
'check',
|
|
30
|
+
'checked',
|
|
31
|
+
'on',
|
|
32
|
+
'enable',
|
|
33
|
+
'enabled',
|
|
34
|
+
];
|
|
35
|
+
const falseWords = [
|
|
36
|
+
'no',
|
|
37
|
+
'nope',
|
|
38
|
+
'false',
|
|
39
|
+
'incorrect',
|
|
40
|
+
'negative',
|
|
41
|
+
'uncheck',
|
|
42
|
+
'unchecked',
|
|
43
|
+
'off',
|
|
44
|
+
'disable',
|
|
45
|
+
'disabled',
|
|
46
|
+
];
|
|
47
|
+
for (const word of trueWords) {
|
|
48
|
+
if (normalized.includes(word))
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
for (const word of falseWords) {
|
|
52
|
+
if (normalized.includes(word))
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Matches a spoken string against a list of options.
|
|
59
|
+
*/
|
|
60
|
+
export function matchOption(spokenText, options) {
|
|
61
|
+
const normalized = spokenText.toLowerCase().trim();
|
|
62
|
+
// Try exact match first
|
|
63
|
+
for (const opt of options) {
|
|
64
|
+
if (opt.value.toLowerCase() === normalized ||
|
|
65
|
+
opt.label.toLowerCase() === normalized) {
|
|
66
|
+
return opt.value;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// Try partial match
|
|
70
|
+
for (const opt of options) {
|
|
71
|
+
if (opt.label.toLowerCase().includes(normalized) ||
|
|
72
|
+
normalized.includes(opt.label.toLowerCase())) {
|
|
73
|
+
return opt.value;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"import-optional.d.ts","sourceRoot":"","sources":["../../src/utils/import-optional.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,wBAAsB,cAAc,CAAC,OAAO,GAAG,OAAO,EACpD,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,OAAO,CAAC,CAGlB"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { generateTheme, getContrastRatio, getLuminance, hexToRgb, meetsContrastAA, meetsContrastAAA, rgbToHex, } from '../color';
|
|
3
|
+
describe('Theme Color Utilities', () => {
|
|
4
|
+
it('should convert hex to rgb correctly', () => {
|
|
5
|
+
expect(hexToRgb('#000000')).toEqual({ r: 0, g: 0, b: 0 });
|
|
6
|
+
expect(hexToRgb('#ffffff')).toEqual({ r: 255, g: 255, b: 255 });
|
|
7
|
+
expect(hexToRgb('#FF5733')).toEqual({ r: 255, g: 87, b: 51 });
|
|
8
|
+
});
|
|
9
|
+
it('should convert rgb to hex correctly', () => {
|
|
10
|
+
expect(rgbToHex(0, 0, 0)).toBe('#000000');
|
|
11
|
+
expect(rgbToHex(255, 255, 255)).toBe('#ffffff');
|
|
12
|
+
expect(rgbToHex(255, 87, 51)).toBe('#ff5733');
|
|
13
|
+
});
|
|
14
|
+
it('should generate a theme palette from a seed color', () => {
|
|
15
|
+
const seed = '#6750A4'; // M3 Baseline Purple
|
|
16
|
+
const theme = generateTheme(seed);
|
|
17
|
+
// Check for critical M3 keys
|
|
18
|
+
expect(theme).toHaveProperty('primary');
|
|
19
|
+
expect(theme).toHaveProperty('onPrimary');
|
|
20
|
+
expect(theme).toHaveProperty('primaryContainer');
|
|
21
|
+
expect(theme).toHaveProperty('onPrimaryContainer');
|
|
22
|
+
expect(theme).toHaveProperty('secondary');
|
|
23
|
+
expect(theme).toHaveProperty('surface');
|
|
24
|
+
expect(theme).toHaveProperty('background');
|
|
25
|
+
expect(theme).toHaveProperty('error');
|
|
26
|
+
// Basic validity check (strings should be hex colors)
|
|
27
|
+
expect(theme.primary).toMatch(/^#[0-9a-fA-F]{6}$/);
|
|
28
|
+
});
|
|
29
|
+
it('should generate different palettes for light and dark modes', () => {
|
|
30
|
+
const seed = '#6750A4';
|
|
31
|
+
const lightTheme = generateTheme(seed, 'light');
|
|
32
|
+
const darkTheme = generateTheme(seed, 'dark');
|
|
33
|
+
expect(lightTheme.primary).not.toBe(darkTheme.primary);
|
|
34
|
+
// In M3, dark mode primary is usually lighter/desaturated compared to light mode
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
describe('Color Contrast Utilities', () => {
|
|
38
|
+
it('should calculate luminance correctly', () => {
|
|
39
|
+
// Black has luminance 0
|
|
40
|
+
expect(getLuminance({ r: 0, g: 0, b: 0 })).toBe(0);
|
|
41
|
+
// White has luminance 1
|
|
42
|
+
expect(getLuminance({ r: 255, g: 255, b: 255 })).toBe(1);
|
|
43
|
+
// Mid gray should be around 0.2
|
|
44
|
+
const midGray = getLuminance({ r: 128, g: 128, b: 128 });
|
|
45
|
+
expect(midGray).toBeGreaterThan(0.1);
|
|
46
|
+
expect(midGray).toBeLessThan(0.3);
|
|
47
|
+
});
|
|
48
|
+
it('should calculate contrast ratio correctly', () => {
|
|
49
|
+
const black = { r: 0, g: 0, b: 0 };
|
|
50
|
+
const white = { r: 255, g: 255, b: 255 };
|
|
51
|
+
// Black on white should be 21:1 (maximum contrast)
|
|
52
|
+
expect(getContrastRatio(black, white)).toBeCloseTo(21, 0);
|
|
53
|
+
// Same color should be 1:1 (no contrast)
|
|
54
|
+
expect(getContrastRatio(black, black)).toBe(1);
|
|
55
|
+
});
|
|
56
|
+
it('should validate WCAG AA contrast requirements', () => {
|
|
57
|
+
// Black on white passes AA
|
|
58
|
+
expect(meetsContrastAA('#000000', '#ffffff')).toBe(true);
|
|
59
|
+
// Light gray on white fails AA for normal text
|
|
60
|
+
expect(meetsContrastAA('#999999', '#ffffff')).toBe(false);
|
|
61
|
+
// Light gray on white passes AA for large text (3:1 threshold)
|
|
62
|
+
expect(meetsContrastAA('#767676', '#ffffff', true)).toBe(true);
|
|
63
|
+
});
|
|
64
|
+
it('should validate WCAG AAA contrast requirements', () => {
|
|
65
|
+
// Black on white passes AAA
|
|
66
|
+
expect(meetsContrastAAA('#000000', '#ffffff')).toBe(true);
|
|
67
|
+
// Medium gray on white fails AAA for normal text (needs 7:1)
|
|
68
|
+
expect(meetsContrastAAA('#666666', '#ffffff')).toBe(false);
|
|
69
|
+
// Darker gray passes AAA for large text (4.5:1 threshold)
|
|
70
|
+
expect(meetsContrastAAA('#595959', '#ffffff', true)).toBe(true);
|
|
71
|
+
});
|
|
72
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { elevationTokens, typographyTokens } from '../typography';
|
|
3
|
+
describe('Typography & Elevation Tokens', () => {
|
|
4
|
+
it('should have valid typography tokens', () => {
|
|
5
|
+
expect(typographyTokens['--md-sys-typescale-body-large-font']).toBeDefined();
|
|
6
|
+
expect(typographyTokens['--md-sys-typescale-display-large-font']).toContain('Roboto');
|
|
7
|
+
});
|
|
8
|
+
it('should have valid elevation tokens', () => {
|
|
9
|
+
expect(elevationTokens['--md-sys-elevation-level1']).toBeDefined();
|
|
10
|
+
});
|
|
11
|
+
});
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
export interface Rgb {
|
|
2
|
+
r: number;
|
|
3
|
+
g: number;
|
|
4
|
+
b: number;
|
|
5
|
+
}
|
|
6
|
+
export interface Hsl {
|
|
7
|
+
h: number;
|
|
8
|
+
s: number;
|
|
9
|
+
l: number;
|
|
10
|
+
}
|
|
11
|
+
export interface Theme {
|
|
12
|
+
primary: string;
|
|
13
|
+
onPrimary: string;
|
|
14
|
+
primaryContainer: string;
|
|
15
|
+
onPrimaryContainer: string;
|
|
16
|
+
secondary: string;
|
|
17
|
+
onSecondary: string;
|
|
18
|
+
secondaryContainer: string;
|
|
19
|
+
onSecondaryContainer: string;
|
|
20
|
+
tertiary: string;
|
|
21
|
+
onTertiary: string;
|
|
22
|
+
tertiaryContainer: string;
|
|
23
|
+
onTertiaryContainer: string;
|
|
24
|
+
error: string;
|
|
25
|
+
onError: string;
|
|
26
|
+
errorContainer: string;
|
|
27
|
+
onErrorContainer: string;
|
|
28
|
+
background: string;
|
|
29
|
+
onBackground: string;
|
|
30
|
+
surface: string;
|
|
31
|
+
onSurface: string;
|
|
32
|
+
surfaceVariant: string;
|
|
33
|
+
onSurfaceVariant: string;
|
|
34
|
+
outline: string;
|
|
35
|
+
outlineVariant: string;
|
|
36
|
+
shadow: string;
|
|
37
|
+
scrim: string;
|
|
38
|
+
inverseSurface: string;
|
|
39
|
+
inverseOnSurface: string;
|
|
40
|
+
inversePrimary: string;
|
|
41
|
+
surfaceDim: string;
|
|
42
|
+
surfaceBright: string;
|
|
43
|
+
surfaceContainerLowest: string;
|
|
44
|
+
surfaceContainerLow: string;
|
|
45
|
+
surfaceContainer: string;
|
|
46
|
+
surfaceContainerHigh: string;
|
|
47
|
+
surfaceContainerHighest: string;
|
|
48
|
+
}
|
|
49
|
+
export declare function hexToRgb(hex: string): Rgb;
|
|
50
|
+
export declare function rgbToHex(r: number, g: number, b: number): string;
|
|
51
|
+
/**
|
|
52
|
+
* Calculate relative luminance of a color per WCAG 2.1
|
|
53
|
+
* https://www.w3.org/WAI/GL/wiki/Relative_luminance
|
|
54
|
+
*/
|
|
55
|
+
export declare function getLuminance(rgb: Rgb): number;
|
|
56
|
+
/**
|
|
57
|
+
* Calculate contrast ratio between two colors per WCAG 2.1
|
|
58
|
+
* Returns a value between 1 and 21
|
|
59
|
+
*/
|
|
60
|
+
export declare function getContrastRatio(fg: Rgb, bg: Rgb): number;
|
|
61
|
+
/**
|
|
62
|
+
* Check if contrast meets WCAG AA standard (4.5:1 for normal text, 3:1 for large text)
|
|
63
|
+
*/
|
|
64
|
+
export declare function meetsContrastAA(fg: string | Rgb, bg: string | Rgb, largeText?: boolean): boolean;
|
|
65
|
+
/**
|
|
66
|
+
* Check if contrast meets WCAG AAA standard (7:1 for normal text, 4.5:1 for large text)
|
|
67
|
+
*/
|
|
68
|
+
export declare function meetsContrastAAA(fg: string | Rgb, bg: string | Rgb, largeText?: boolean): boolean;
|
|
69
|
+
export declare function generateTheme(seedColor: string, mode?: 'light' | 'dark'): Theme;
|
|
70
|
+
//# sourceMappingURL=color.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"color.d.ts","sourceRoot":"","sources":["../../../src/utils/theme/color.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,GAAG;IAClB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,MAAM,WAAW,GAAG;IAClB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAGD,MAAM,WAAW,KAAK;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,sBAAsB,EAAE,MAAM,CAAC;IAC/B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,gBAAgB,EAAE,MAAM,CAAC;IACzB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,uBAAuB,EAAE,MAAM,CAAC;CACjC;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAMzC;AAED,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAMhE;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,CAM7C;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,GAAG,MAAM,CAMzD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,EAAE,EAAE,MAAM,GAAG,GAAG,EAChB,EAAE,EAAE,MAAM,GAAG,GAAG,EAChB,SAAS,UAAQ,GAChB,OAAO,CAKT;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,EAAE,EAAE,MAAM,GAAG,GAAG,EAChB,EAAE,EAAE,MAAM,GAAG,GAAG,EAChB,SAAS,UAAQ,GAChB,OAAO,CAKT;AAmED,wBAAgB,aAAa,CAC3B,SAAS,EAAE,MAAM,EACjB,IAAI,GAAE,OAAO,GAAG,MAAgB,GAC/B,KAAK,CA2HP"}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
export function hexToRgb(hex) {
|
|
2
|
+
const cleanHex = hex.replace('#', '');
|
|
3
|
+
const r = parseInt(cleanHex.substring(0, 2), 16);
|
|
4
|
+
const g = parseInt(cleanHex.substring(2, 4), 16);
|
|
5
|
+
const b = parseInt(cleanHex.substring(4, 6), 16);
|
|
6
|
+
return { r, g, b };
|
|
7
|
+
}
|
|
8
|
+
export function rgbToHex(r, g, b) {
|
|
9
|
+
const toHex = (c) => {
|
|
10
|
+
const hex = Math.round(Math.max(0, Math.min(255, c))).toString(16);
|
|
11
|
+
return hex.length === 1 ? `0${hex}` : hex;
|
|
12
|
+
};
|
|
13
|
+
return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Calculate relative luminance of a color per WCAG 2.1
|
|
17
|
+
* https://www.w3.org/WAI/GL/wiki/Relative_luminance
|
|
18
|
+
*/
|
|
19
|
+
export function getLuminance(rgb) {
|
|
20
|
+
const [r, g, b] = [rgb.r, rgb.g, rgb.b].map((c) => {
|
|
21
|
+
const sRGB = c / 255;
|
|
22
|
+
return sRGB <= 0.03928 ? sRGB / 12.92 : ((sRGB + 0.055) / 1.055) ** 2.4;
|
|
23
|
+
});
|
|
24
|
+
return 0.2126 * r + 0.7152 * g + 0.0722 * b;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Calculate contrast ratio between two colors per WCAG 2.1
|
|
28
|
+
* Returns a value between 1 and 21
|
|
29
|
+
*/
|
|
30
|
+
export function getContrastRatio(fg, bg) {
|
|
31
|
+
const L1 = getLuminance(fg);
|
|
32
|
+
const L2 = getLuminance(bg);
|
|
33
|
+
const lighter = Math.max(L1, L2);
|
|
34
|
+
const darker = Math.min(L1, L2);
|
|
35
|
+
return (lighter + 0.05) / (darker + 0.05);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Check if contrast meets WCAG AA standard (4.5:1 for normal text, 3:1 for large text)
|
|
39
|
+
*/
|
|
40
|
+
export function meetsContrastAA(fg, bg, largeText = false) {
|
|
41
|
+
const fgRgb = typeof fg === 'string' ? hexToRgb(fg) : fg;
|
|
42
|
+
const bgRgb = typeof bg === 'string' ? hexToRgb(bg) : bg;
|
|
43
|
+
const ratio = getContrastRatio(fgRgb, bgRgb);
|
|
44
|
+
return ratio >= (largeText ? 3 : 4.5);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Check if contrast meets WCAG AAA standard (7:1 for normal text, 4.5:1 for large text)
|
|
48
|
+
*/
|
|
49
|
+
export function meetsContrastAAA(fg, bg, largeText = false) {
|
|
50
|
+
const fgRgb = typeof fg === 'string' ? hexToRgb(fg) : fg;
|
|
51
|
+
const bgRgb = typeof bg === 'string' ? hexToRgb(bg) : bg;
|
|
52
|
+
const ratio = getContrastRatio(fgRgb, bgRgb);
|
|
53
|
+
return ratio >= (largeText ? 4.5 : 7);
|
|
54
|
+
}
|
|
55
|
+
function rgbToHsl(r, g, b) {
|
|
56
|
+
r /= 255;
|
|
57
|
+
g /= 255;
|
|
58
|
+
b /= 255;
|
|
59
|
+
const max = Math.max(r, g, b);
|
|
60
|
+
const min = Math.min(r, g, b);
|
|
61
|
+
let h = 0, s = 0, l = (max + min) / 2;
|
|
62
|
+
if (max !== min) {
|
|
63
|
+
const d = max - min;
|
|
64
|
+
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
65
|
+
switch (max) {
|
|
66
|
+
case r:
|
|
67
|
+
h = (g - b) / d + (g < b ? 6 : 0);
|
|
68
|
+
break;
|
|
69
|
+
case g:
|
|
70
|
+
h = (b - r) / d + 2;
|
|
71
|
+
break;
|
|
72
|
+
case b:
|
|
73
|
+
h = (r - g) / d + 4;
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
h /= 6;
|
|
77
|
+
}
|
|
78
|
+
return { h: h * 360, s: s * 100, l: l * 100 };
|
|
79
|
+
}
|
|
80
|
+
function hslToRgb(h, s, l) {
|
|
81
|
+
h /= 360;
|
|
82
|
+
s /= 100;
|
|
83
|
+
l /= 100;
|
|
84
|
+
let r, g, b;
|
|
85
|
+
if (s === 0) {
|
|
86
|
+
r = g = b = l;
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
const hue2rgb = (p, q, t) => {
|
|
90
|
+
if (t < 0)
|
|
91
|
+
t += 1;
|
|
92
|
+
if (t > 1)
|
|
93
|
+
t -= 1;
|
|
94
|
+
if (t < 1 / 6)
|
|
95
|
+
return p + (q - p) * 6 * t;
|
|
96
|
+
if (t < 1 / 2)
|
|
97
|
+
return q;
|
|
98
|
+
if (t < 2 / 3)
|
|
99
|
+
return p + (q - p) * (2 / 3 - t) * 6;
|
|
100
|
+
return p;
|
|
101
|
+
};
|
|
102
|
+
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
|
103
|
+
const p = 2 * l - q;
|
|
104
|
+
r = hue2rgb(p, q, h + 1 / 3);
|
|
105
|
+
g = hue2rgb(p, q, h);
|
|
106
|
+
b = hue2rgb(p, q, h - 1 / 3);
|
|
107
|
+
}
|
|
108
|
+
return { r: r * 255, g: g * 255, b: b * 255 };
|
|
109
|
+
}
|
|
110
|
+
function hslToHex(h, s, l) {
|
|
111
|
+
const { r, g, b } = hslToRgb(h, s, l);
|
|
112
|
+
return rgbToHex(r, g, b);
|
|
113
|
+
}
|
|
114
|
+
// Generate a color with the same Hue and Saturation but specific Lightness
|
|
115
|
+
function tone(h, s, l) {
|
|
116
|
+
return hslToHex(h, s, l);
|
|
117
|
+
}
|
|
118
|
+
export function generateTheme(seedColor, mode = 'light') {
|
|
119
|
+
const rgb = hexToRgb(seedColor);
|
|
120
|
+
const hsl = rgbToHsl(rgb.r, rgb.g, rgb.b);
|
|
121
|
+
// Tonal Palettes (Simplified M3 Logic)
|
|
122
|
+
// Primary: Keep seed hue/sat
|
|
123
|
+
const p_h = hsl.h;
|
|
124
|
+
const p_s = Math.max(hsl.s, 40); // Ensure some vibrancy
|
|
125
|
+
// Secondary: Less vibrant
|
|
126
|
+
const s_h = p_h;
|
|
127
|
+
const s_s = Math.max(p_s / 3, 20);
|
|
128
|
+
// Tertiary: Shifted hue
|
|
129
|
+
const t_h = (p_h + 60) % 360;
|
|
130
|
+
const t_s = Math.max(p_s / 1.5, 30);
|
|
131
|
+
// Neutral
|
|
132
|
+
const n_h = p_h;
|
|
133
|
+
const n_s = Math.min(p_s / 10, 8); // Very low saturation
|
|
134
|
+
// Neutral Variant
|
|
135
|
+
const nv_h = p_h;
|
|
136
|
+
const nv_s = Math.min(p_s / 6, 16);
|
|
137
|
+
// Error (Red)
|
|
138
|
+
const e_h = 0; // Red
|
|
139
|
+
const e_s = 80;
|
|
140
|
+
if (mode === 'light') {
|
|
141
|
+
return {
|
|
142
|
+
primary: tone(p_h, p_s, 40),
|
|
143
|
+
onPrimary: tone(p_h, p_s, 100),
|
|
144
|
+
primaryContainer: tone(p_h, p_s, 90),
|
|
145
|
+
onPrimaryContainer: tone(p_h, p_s, 10),
|
|
146
|
+
secondary: tone(s_h, s_s, 40),
|
|
147
|
+
onSecondary: tone(s_h, s_s, 100),
|
|
148
|
+
secondaryContainer: tone(s_h, s_s, 90),
|
|
149
|
+
onSecondaryContainer: tone(s_h, s_s, 10),
|
|
150
|
+
tertiary: tone(t_h, t_s, 40),
|
|
151
|
+
onTertiary: tone(t_h, t_s, 100),
|
|
152
|
+
tertiaryContainer: tone(t_h, t_s, 90),
|
|
153
|
+
onTertiaryContainer: tone(t_h, t_s, 10),
|
|
154
|
+
error: tone(e_h, e_s, 40),
|
|
155
|
+
onError: tone(e_h, e_s, 100),
|
|
156
|
+
errorContainer: tone(e_h, e_s, 90),
|
|
157
|
+
onErrorContainer: tone(e_h, e_s, 10),
|
|
158
|
+
background: tone(n_h, n_s, 99),
|
|
159
|
+
onBackground: tone(n_h, n_s, 10),
|
|
160
|
+
surface: tone(n_h, n_s, 99),
|
|
161
|
+
onSurface: tone(n_h, n_s, 10),
|
|
162
|
+
surfaceVariant: tone(nv_h, nv_s, 90),
|
|
163
|
+
onSurfaceVariant: tone(nv_h, nv_s, 30),
|
|
164
|
+
outline: tone(nv_h, nv_s, 50),
|
|
165
|
+
outlineVariant: tone(nv_h, nv_s, 80),
|
|
166
|
+
shadow: tone(0, 0, 0),
|
|
167
|
+
scrim: tone(0, 0, 0),
|
|
168
|
+
inverseSurface: tone(n_h, n_s, 20),
|
|
169
|
+
inverseOnSurface: tone(n_h, n_s, 95),
|
|
170
|
+
inversePrimary: tone(p_h, p_s, 80),
|
|
171
|
+
surfaceDim: tone(n_h, n_s, 87),
|
|
172
|
+
surfaceBright: tone(n_h, n_s, 98),
|
|
173
|
+
surfaceContainerLowest: tone(n_h, n_s, 100),
|
|
174
|
+
surfaceContainerLow: tone(n_h, n_s, 96),
|
|
175
|
+
surfaceContainer: tone(n_h, n_s, 94),
|
|
176
|
+
surfaceContainerHigh: tone(n_h, n_s, 92),
|
|
177
|
+
surfaceContainerHighest: tone(n_h, n_s, 90),
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
// Dark Mode mappings
|
|
182
|
+
return {
|
|
183
|
+
primary: tone(p_h, p_s, 80),
|
|
184
|
+
onPrimary: tone(p_h, p_s, 20),
|
|
185
|
+
primaryContainer: tone(p_h, p_s, 30),
|
|
186
|
+
onPrimaryContainer: tone(p_h, p_s, 90),
|
|
187
|
+
secondary: tone(s_h, s_s, 80),
|
|
188
|
+
onSecondary: tone(s_h, s_s, 20),
|
|
189
|
+
secondaryContainer: tone(s_h, s_s, 30),
|
|
190
|
+
onSecondaryContainer: tone(s_h, s_s, 90),
|
|
191
|
+
tertiary: tone(t_h, t_s, 80),
|
|
192
|
+
onTertiary: tone(t_h, t_s, 20),
|
|
193
|
+
tertiaryContainer: tone(t_h, t_s, 30),
|
|
194
|
+
onTertiaryContainer: tone(t_h, t_s, 90),
|
|
195
|
+
error: tone(e_h, e_s, 80),
|
|
196
|
+
onError: tone(e_h, e_s, 20),
|
|
197
|
+
errorContainer: tone(e_h, e_s, 30),
|
|
198
|
+
onErrorContainer: tone(e_h, e_s, 90),
|
|
199
|
+
background: tone(n_h, n_s, 10),
|
|
200
|
+
onBackground: tone(n_h, n_s, 90),
|
|
201
|
+
surface: tone(n_h, n_s, 10),
|
|
202
|
+
onSurface: tone(n_h, n_s, 90),
|
|
203
|
+
surfaceVariant: tone(nv_h, nv_s, 30),
|
|
204
|
+
onSurfaceVariant: tone(nv_h, nv_s, 80),
|
|
205
|
+
outline: tone(nv_h, nv_s, 60),
|
|
206
|
+
outlineVariant: tone(nv_h, nv_s, 30),
|
|
207
|
+
shadow: tone(0, 0, 0),
|
|
208
|
+
scrim: tone(0, 0, 0),
|
|
209
|
+
inverseSurface: tone(n_h, n_s, 90),
|
|
210
|
+
inverseOnSurface: tone(n_h, n_s, 20),
|
|
211
|
+
inversePrimary: tone(p_h, p_s, 40),
|
|
212
|
+
surfaceDim: tone(n_h, n_s, 6),
|
|
213
|
+
surfaceBright: tone(n_h, n_s, 24),
|
|
214
|
+
surfaceContainerLowest: tone(n_h, n_s, 4),
|
|
215
|
+
surfaceContainerLow: tone(n_h, n_s, 10),
|
|
216
|
+
surfaceContainer: tone(n_h, n_s, 12),
|
|
217
|
+
surfaceContainerHigh: tone(n_h, n_s, 17),
|
|
218
|
+
surfaceContainerHighest: tone(n_h, n_s, 22),
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export declare const typographyTokens: {
|
|
2
|
+
'--smrt-font-family': string;
|
|
3
|
+
'--md-sys-typescale-display-large-font': string;
|
|
4
|
+
'--md-sys-typescale-display-medium-font': string;
|
|
5
|
+
'--md-sys-typescale-display-small-font': string;
|
|
6
|
+
'--md-sys-typescale-headline-large-font': string;
|
|
7
|
+
'--md-sys-typescale-headline-medium-font': string;
|
|
8
|
+
'--md-sys-typescale-headline-small-font': string;
|
|
9
|
+
'--md-sys-typescale-title-large-font': string;
|
|
10
|
+
'--md-sys-typescale-title-medium-font': string;
|
|
11
|
+
'--md-sys-typescale-title-small-font': string;
|
|
12
|
+
'--md-sys-typescale-label-large-font': string;
|
|
13
|
+
'--md-sys-typescale-label-medium-font': string;
|
|
14
|
+
'--md-sys-typescale-label-small-font': string;
|
|
15
|
+
'--md-sys-typescale-body-large-font': string;
|
|
16
|
+
'--md-sys-typescale-body-medium-font': string;
|
|
17
|
+
'--md-sys-typescale-body-small-font': string;
|
|
18
|
+
};
|
|
19
|
+
export declare const elevationTokens: {
|
|
20
|
+
'--md-sys-elevation-level0': string;
|
|
21
|
+
'--md-sys-elevation-level1': string;
|
|
22
|
+
'--md-sys-elevation-level2': string;
|
|
23
|
+
'--md-sys-elevation-level3': string;
|
|
24
|
+
'--md-sys-elevation-level4': string;
|
|
25
|
+
'--md-sys-elevation-level5': string;
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=typography.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typography.d.ts","sourceRoot":"","sources":["../../../src/utils/theme/typography.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;CAuB5B,CAAC;AAGF,eAAO,MAAM,eAAe;;;;;;;CAY3B,CAAC"}
|