@bug-on/md3-react 2.0.2 → 3.0.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/.turbo/turbo-build.log +33 -0
- package/CHANGELOG.md +55 -0
- package/dist/index.css +23 -0
- package/dist/index.css.d.ts +2 -0
- package/dist/index.d.mts +6127 -0
- package/dist/index.d.ts +6127 -69
- package/dist/index.js +2536 -665
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2443 -603
- package/dist/index.mjs.map +1 -1
- package/dist/material-symbols-cdn.css.d.ts +2 -0
- package/dist/material-symbols-self-hosted.css.d.ts +2 -0
- package/dist/typography.css.d.ts +2 -0
- package/package.json +23 -19
- package/scripts/copy-assets.js +82 -0
- package/src/assets/fonts/GoogleSansFlex-VariableFont.woff2 +0 -0
- package/src/assets/fonts/MaterialSymbolsOutlined-VariableFont_FILL,GRAD,opsz,wght.ttf +0 -0
- package/src/assets/fonts/MaterialSymbolsRounded-VariableFont_FILL,GRAD,opsz,wght.ttf +0 -0
- package/src/assets/fonts/MaterialSymbolsSharp-VariableFont_FILL,GRAD,opsz,wght.ttf +0 -0
- package/src/assets/loading-indicator.svg +19 -0
- package/src/assets/material-symbols-cdn.css +65 -0
- package/src/assets/material-symbols-self-hosted.css +90 -0
- package/src/css.d.ts +20 -0
- package/{dist/hooks/index.d.ts → src/hooks/index.ts} +1 -0
- package/src/hooks/useClickOutside.ts +37 -0
- package/src/hooks/useMediaQuery.ts +28 -0
- package/src/hooks/useRipple.ts +88 -0
- package/src/index.css +23 -0
- package/src/index.ts +349 -0
- package/src/lib/material-symbols-preconnect.tsx +82 -0
- package/src/lib/theme-utils.ts +180 -0
- package/src/lib/utils.ts +6 -0
- package/src/test/button.test.tsx +59 -0
- package/src/test/icon.test.tsx +91 -0
- package/src/test/loading-indicator.test.tsx +128 -0
- package/src/test/progress-indicator.test.tsx +306 -0
- package/src/test/setup.ts +80 -0
- package/src/test/typography.test.tsx +206 -0
- package/src/types/index.ts +7 -0
- package/src/types/md3.ts +31 -0
- package/src/ui/Text.tsx +60 -0
- package/src/ui/__snapshots__/divider.test.tsx.snap +63 -0
- package/src/ui/app-bar/app-bar-column.tsx +99 -0
- package/src/ui/app-bar/app-bar-item-button.tsx +71 -0
- package/src/ui/app-bar/app-bar-items.test.tsx +89 -0
- package/src/ui/app-bar/app-bar-overflow-indicator.tsx +108 -0
- package/src/ui/app-bar/app-bar-row.tsx +104 -0
- package/src/ui/app-bar/app-bar.test.tsx +87 -0
- package/src/ui/app-bar/app-bar.tokens.ts +223 -0
- package/src/ui/app-bar/app-bar.types.ts +441 -0
- package/src/ui/app-bar/bottom-app-bar.test.tsx +42 -0
- package/src/ui/app-bar/bottom-app-bar.tsx +84 -0
- package/src/ui/app-bar/docked-toolbar.test.tsx +34 -0
- package/src/ui/app-bar/docked-toolbar.tsx +54 -0
- package/src/ui/app-bar/flexible-app-bar.test.tsx +75 -0
- package/src/ui/app-bar/hooks/use-app-bar-scroll.ts +110 -0
- package/src/ui/app-bar/hooks/use-flexible-app-bar.ts +123 -0
- package/{dist/ui/app-bar/index.d.ts → src/ui/app-bar/index.ts} +35 -2
- package/src/ui/app-bar/large-flexible-app-bar.tsx +165 -0
- package/src/ui/app-bar/medium-flexible-app-bar.tsx +167 -0
- package/src/ui/app-bar/search-app-bar.test.tsx +49 -0
- package/src/ui/app-bar/search-app-bar.tsx +176 -0
- package/src/ui/app-bar/search-view.tsx +227 -0
- package/src/ui/app-bar/small-app-bar.test.tsx +48 -0
- package/src/ui/app-bar/small-app-bar.tsx +203 -0
- package/src/ui/badge.test.tsx +345 -0
- package/src/ui/badge.tsx +282 -0
- package/src/ui/button-group.test.tsx +71 -0
- package/src/ui/button-group.tsx +350 -0
- package/src/ui/button.test.tsx +297 -0
- package/src/ui/button.tsx +669 -0
- package/src/ui/card.test.tsx +187 -0
- package/src/ui/card.tsx +259 -0
- package/src/ui/checkbox.test.tsx +423 -0
- package/src/ui/checkbox.tsx +525 -0
- package/src/ui/chip.test.tsx +292 -0
- package/src/ui/chip.tsx +548 -0
- package/src/ui/code-block.tsx +219 -0
- package/src/ui/dialog.test.tsx +300 -0
- package/src/ui/dialog.tsx +384 -0
- package/src/ui/divider.test.tsx +314 -0
- package/src/ui/divider.tsx +412 -0
- package/src/ui/drawer.tsx +240 -0
- package/src/ui/fab-menu.test.tsx +494 -0
- package/src/ui/fab-menu.tsx +739 -0
- package/src/ui/fab.test.tsx +232 -0
- package/src/ui/fab.tsx +505 -0
- package/src/ui/icon-button.test.tsx +515 -0
- package/src/ui/icon-button.tsx +525 -0
- package/src/ui/icon.test.tsx +197 -0
- package/src/ui/icon.tsx +179 -0
- package/src/ui/loading-indicator.test.tsx +73 -0
- package/src/ui/loading-indicator.tsx +312 -0
- package/src/ui/menu/context-menu.tsx +275 -0
- package/src/ui/menu/index.ts +77 -0
- package/src/ui/menu/menu-animations.ts +102 -0
- package/src/ui/menu/menu-context.tsx +99 -0
- package/src/ui/menu/menu-divider.tsx +47 -0
- package/src/ui/menu/menu-group.tsx +200 -0
- package/src/ui/menu/menu-item.tsx +294 -0
- package/src/ui/menu/menu-tokens.ts +208 -0
- package/src/ui/menu/menu-types.ts +313 -0
- package/src/ui/menu/menu.test.tsx +624 -0
- package/src/ui/menu/menu.tsx +289 -0
- package/src/ui/menu/sub-menu.tsx +223 -0
- package/src/ui/menu/vertical-menu.tsx +382 -0
- package/src/ui/navigation-rail.test.tsx +404 -0
- package/src/ui/navigation-rail.tsx +604 -0
- package/src/ui/progress-indicator/circular.tsx +248 -0
- package/src/ui/progress-indicator/hooks.ts +51 -0
- package/{dist/ui/progress-indicator/index.d.ts → src/ui/progress-indicator/index.tsx} +20 -2
- package/src/ui/progress-indicator/linear-flat.tsx +83 -0
- package/src/ui/progress-indicator/linear-wavy.tsx +243 -0
- package/src/ui/progress-indicator/linear.tsx +143 -0
- package/src/ui/progress-indicator/types.ts +158 -0
- package/src/ui/progress-indicator/utils.ts +73 -0
- package/src/ui/radio-button.test.tsx +407 -0
- package/src/ui/radio-button.tsx +551 -0
- package/src/ui/ripple.test.tsx +72 -0
- package/src/ui/ripple.tsx +234 -0
- package/src/ui/scroll-area.test.tsx +58 -0
- package/src/ui/scroll-area.tsx +139 -0
- package/src/ui/search/animated-placeholder.tsx +145 -0
- package/src/ui/search/hooks/use-search-keyboard.test.ts +202 -0
- package/src/ui/search/hooks/use-search-keyboard.ts +104 -0
- package/src/ui/search/hooks/use-search-view-focus.test.ts +96 -0
- package/src/ui/search/hooks/use-search-view-focus.ts +24 -0
- package/src/ui/search/index.ts +44 -0
- package/src/ui/search/search-bar.tsx +220 -0
- package/src/ui/search/search-context.tsx +42 -0
- package/src/ui/search/search-view-docked.tsx +194 -0
- package/src/ui/search/search-view-fullscreen.tsx +247 -0
- package/src/ui/search/search.test.tsx +233 -0
- package/src/ui/search/search.tokens.ts +134 -0
- package/src/ui/search/search.tsx +131 -0
- package/src/ui/search/search.types.ts +154 -0
- package/src/ui/search/trailing-action.tsx +49 -0
- package/src/ui/shared/constants.ts +122 -0
- package/{dist/ui/shared/touch-target.d.ts → src/ui/shared/touch-target.tsx} +13 -1
- package/src/ui/slider/hooks/useSliderMath.ts +195 -0
- package/{dist/ui/slider/index.d.ts → src/ui/slider/index.ts} +12 -1
- package/src/ui/slider/range-slider.tsx +561 -0
- package/src/ui/slider/slider-thumb.tsx +379 -0
- package/src/ui/slider/slider-track.tsx +912 -0
- package/src/ui/slider/slider.tokens.ts +189 -0
- package/src/ui/slider/slider.tsx +259 -0
- package/src/ui/slider/slider.types.ts +288 -0
- package/src/ui/snackbar/index.ts +20 -0
- package/src/ui/snackbar/snackbar.test.tsx +338 -0
- package/src/ui/snackbar/snackbar.tsx +476 -0
- package/{dist/ui/switch/index.d.ts → src/ui/switch/index.ts} +1 -0
- package/src/ui/switch/switch.stories.tsx +309 -0
- package/src/ui/switch/switch.test.tsx +243 -0
- package/src/ui/switch/switch.tokens.ts +89 -0
- package/src/ui/switch/switch.tsx +504 -0
- package/src/ui/switch/switch.types.ts +62 -0
- package/{dist/ui/tabs/index.d.ts → src/ui/tabs/index.ts} +8 -1
- package/src/ui/tabs/tab.tsx +407 -0
- package/src/ui/tabs/tabs-content.tsx +89 -0
- package/src/ui/tabs/tabs-list.tsx +146 -0
- package/src/ui/tabs/tabs.test.tsx +290 -0
- package/src/ui/tabs/tabs.tokens.ts +121 -0
- package/src/ui/tabs/tabs.tsx +229 -0
- package/src/ui/tabs/tabs.types.ts +185 -0
- package/{dist/ui/text-field/index.d.ts → src/ui/text-field/index.ts} +8 -1
- package/src/ui/text-field/subcomponents/active-indicator.tsx +67 -0
- package/src/ui/text-field/subcomponents/floating-label.tsx +161 -0
- package/src/ui/text-field/subcomponents/leading-icon.tsx +46 -0
- package/src/ui/text-field/subcomponents/outline-container.tsx +170 -0
- package/src/ui/text-field/subcomponents/prefix-suffix.tsx +59 -0
- package/src/ui/text-field/subcomponents/supporting-text.tsx +145 -0
- package/src/ui/text-field/subcomponents/trailing-icon.tsx +199 -0
- package/src/ui/text-field/text-field.test.tsx +454 -0
- package/src/ui/text-field/text-field.tokens.ts +104 -0
- package/src/ui/text-field/text-field.tsx +548 -0
- package/src/ui/text-field/text-field.types.ts +180 -0
- package/src/ui/theme-provider/index.tsx +190 -0
- package/src/ui/toc.test.tsx +108 -0
- package/src/ui/toc.tsx +172 -0
- package/src/ui/tooltip/plain-tooltip.tsx +63 -0
- package/src/ui/tooltip/rich-tooltip.tsx +94 -0
- package/src/ui/tooltip/tooltip-box.tsx +266 -0
- package/src/ui/tooltip/tooltip-caret-shape.tsx +68 -0
- package/src/ui/tooltip/tooltip.tokens.ts +26 -0
- package/src/ui/tooltip/tooltip.types.ts +70 -0
- package/src/ui/tooltip/use-tooltip-position.ts +208 -0
- package/src/ui/tooltip/use-tooltip-state.ts +41 -0
- package/src/ui/typography/__tests__/typography.test.tsx +170 -0
- package/{dist/ui/typography/index.d.ts → src/ui/typography/index.ts} +21 -3
- package/src/ui/typography/type-scale-tokens.ts +205 -0
- package/src/ui/typography/typography-key-tokens.ts +43 -0
- package/src/ui/typography/typography-tokens.ts +360 -0
- package/src/ui/typography/typography.css +22 -0
- package/src/ui/typography/typography.tsx +559 -0
- package/test-render.tsx +4 -0
- package/test-shadow.html +26 -0
- package/test_output.txt +164 -0
- package/test_output_v2.txt +5 -0
- package/tsconfig.build.json +10 -0
- package/tsconfig.json +18 -0
- package/tsup.config.ts +20 -0
- package/vitest.config.ts +11 -0
- package/dist/hooks/useMediaQuery.d.ts +0 -11
- package/dist/hooks/useRipple.d.ts +0 -26
- package/dist/lib/material-symbols-preconnect.d.ts +0 -42
- package/dist/lib/theme-utils.d.ts +0 -63
- package/dist/lib/utils.d.ts +0 -2
- package/dist/types/index.d.ts +0 -1
- package/dist/types/md3.d.ts +0 -14
- package/dist/ui/app-bar/app-bar-column.d.ts +0 -28
- package/dist/ui/app-bar/app-bar-item-button.d.ts +0 -16
- package/dist/ui/app-bar/app-bar-overflow-indicator.d.ts +0 -18
- package/dist/ui/app-bar/app-bar-row.d.ts +0 -36
- package/dist/ui/app-bar/app-bar.tokens.d.ts +0 -184
- package/dist/ui/app-bar/app-bar.types.d.ts +0 -392
- package/dist/ui/app-bar/bottom-app-bar.d.ts +0 -31
- package/dist/ui/app-bar/docked-toolbar.d.ts +0 -25
- package/dist/ui/app-bar/hooks/use-app-bar-scroll.d.ts +0 -42
- package/dist/ui/app-bar/hooks/use-flexible-app-bar.d.ts +0 -37
- package/dist/ui/app-bar/large-flexible-app-bar.d.ts +0 -26
- package/dist/ui/app-bar/medium-flexible-app-bar.d.ts +0 -28
- package/dist/ui/app-bar/search-app-bar.d.ts +0 -43
- package/dist/ui/app-bar/search-view.d.ts +0 -54
- package/dist/ui/app-bar/small-app-bar.d.ts +0 -37
- package/dist/ui/badge.d.ts +0 -125
- package/dist/ui/button-group.d.ts +0 -59
- package/dist/ui/button.d.ts +0 -148
- package/dist/ui/card.d.ts +0 -62
- package/dist/ui/checkbox.d.ts +0 -82
- package/dist/ui/chip.d.ts +0 -110
- package/dist/ui/code-block.d.ts +0 -14
- package/dist/ui/dialog.d.ts +0 -111
- package/dist/ui/divider.d.ts +0 -164
- package/dist/ui/drawer.d.ts +0 -39
- package/dist/ui/dropdown.d.ts +0 -29
- package/dist/ui/fab-menu.d.ts +0 -204
- package/dist/ui/fab.d.ts +0 -162
- package/dist/ui/icon-button.d.ts +0 -131
- package/dist/ui/icon.d.ts +0 -88
- package/dist/ui/loading-indicator.d.ts +0 -42
- package/dist/ui/navigation-rail.d.ts +0 -29
- package/dist/ui/progress-indicator/circular.d.ts +0 -3
- package/dist/ui/progress-indicator/hooks.d.ts +0 -3
- package/dist/ui/progress-indicator/linear-flat.d.ts +0 -10
- package/dist/ui/progress-indicator/linear-wavy.d.ts +0 -18
- package/dist/ui/progress-indicator/linear.d.ts +0 -3
- package/dist/ui/progress-indicator/types.d.ts +0 -151
- package/dist/ui/progress-indicator/utils.d.ts +0 -3
- package/dist/ui/radio-button.d.ts +0 -106
- package/dist/ui/ripple.d.ts +0 -126
- package/dist/ui/scroll-area.d.ts +0 -27
- package/dist/ui/shared/constants.d.ts +0 -86
- package/dist/ui/slider/hooks/useSliderMath.d.ts +0 -101
- package/dist/ui/slider/range-slider.d.ts +0 -47
- package/dist/ui/slider/slider-thumb.d.ts +0 -33
- package/dist/ui/slider/slider-track.d.ts +0 -25
- package/dist/ui/slider/slider.d.ts +0 -60
- package/dist/ui/slider/slider.tokens.d.ts +0 -151
- package/dist/ui/slider/slider.types.d.ts +0 -259
- package/dist/ui/snackbar/index.d.ts +0 -6
- package/dist/ui/snackbar/snackbar.d.ts +0 -197
- package/dist/ui/switch/switch.d.ts +0 -30
- package/dist/ui/switch/switch.stories.d.ts +0 -48
- package/dist/ui/switch/switch.tokens.d.ts +0 -67
- package/dist/ui/switch/switch.types.d.ts +0 -59
- package/dist/ui/tabs/tab.d.ts +0 -43
- package/dist/ui/tabs/tabs-content.d.ts +0 -36
- package/dist/ui/tabs/tabs-list.d.ts +0 -40
- package/dist/ui/tabs/tabs.d.ts +0 -60
- package/dist/ui/tabs/tabs.tokens.d.ts +0 -94
- package/dist/ui/tabs/tabs.types.d.ts +0 -172
- package/dist/ui/text-field/subcomponents/active-indicator.d.ts +0 -24
- package/dist/ui/text-field/subcomponents/floating-label.d.ts +0 -43
- package/dist/ui/text-field/subcomponents/leading-icon.d.ts +0 -23
- package/dist/ui/text-field/subcomponents/outline-container.d.ts +0 -42
- package/dist/ui/text-field/subcomponents/prefix-suffix.d.ts +0 -24
- package/dist/ui/text-field/subcomponents/supporting-text.d.ts +0 -37
- package/dist/ui/text-field/subcomponents/trailing-icon.d.ts +0 -41
- package/dist/ui/text-field/text-field.d.ts +0 -49
- package/dist/ui/text-field/text-field.tokens.d.ts +0 -76
- package/dist/ui/text-field/text-field.types.d.ts +0 -126
- package/dist/ui/theme-provider/index.d.ts +0 -48
- package/dist/ui/toc.d.ts +0 -80
- package/dist/ui/tooltip/plain-tooltip.d.ts +0 -2
- package/dist/ui/tooltip/rich-tooltip.d.ts +0 -2
- package/dist/ui/tooltip/tooltip-box.d.ts +0 -2
- package/dist/ui/tooltip/tooltip-caret-shape.d.ts +0 -9
- package/dist/ui/tooltip/tooltip.tokens.d.ts +0 -26
- package/dist/ui/tooltip/tooltip.types.d.ts +0 -56
- package/dist/ui/tooltip/use-tooltip-position.d.ts +0 -8
- package/dist/ui/tooltip/use-tooltip-state.d.ts +0 -2
- package/dist/ui/typography/type-scale-tokens.d.ts +0 -162
- package/dist/ui/typography/typography-key-tokens.d.ts +0 -40
- package/dist/ui/typography/typography-tokens.d.ts +0 -220
- package/dist/ui/typography/typography.d.ts +0 -265
- /package/{dist/ui/tooltip/index.d.ts → src/ui/tooltip/index.ts} +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bug-on/md3-react",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "Material Design 3 Expressive React components",
|
|
5
5
|
"author": "Bug Ổn",
|
|
6
6
|
"license": "MIT",
|
|
@@ -27,23 +27,27 @@
|
|
|
27
27
|
"import": "./dist/index.mjs",
|
|
28
28
|
"require": "./dist/index.js"
|
|
29
29
|
},
|
|
30
|
-
"./typography.css":
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
30
|
+
"./typography.css": {
|
|
31
|
+
"types": "./dist/typography.css.d.ts",
|
|
32
|
+
"default": "./dist/typography.css"
|
|
33
|
+
},
|
|
34
|
+
"./index.css": {
|
|
35
|
+
"types": "./dist/index.css.d.ts",
|
|
36
|
+
"default": "./dist/index.css"
|
|
37
|
+
},
|
|
38
|
+
"./material-symbols-cdn.css": {
|
|
39
|
+
"types": "./dist/material-symbols-cdn.css.d.ts",
|
|
40
|
+
"default": "./dist/material-symbols-cdn.css"
|
|
41
|
+
},
|
|
42
|
+
"./material-symbols-self-hosted.css": {
|
|
43
|
+
"types": "./dist/material-symbols-self-hosted.css.d.ts",
|
|
44
|
+
"default": "./dist/material-symbols-self-hosted.css"
|
|
45
|
+
}
|
|
42
46
|
},
|
|
43
47
|
"peerDependencies": {
|
|
44
|
-
"motion": ">=12.0.0",
|
|
45
48
|
"react": "^19.0.0",
|
|
46
|
-
"react-dom": "^19.0.0"
|
|
49
|
+
"react-dom": "^19.0.0",
|
|
50
|
+
"motion": ">=12.0.0"
|
|
47
51
|
},
|
|
48
52
|
"peerDependenciesMeta": {
|
|
49
53
|
"motion": {
|
|
@@ -52,6 +56,7 @@
|
|
|
52
56
|
},
|
|
53
57
|
"dependencies": {
|
|
54
58
|
"@material/material-color-utilities": "^0.3.0",
|
|
59
|
+
"@radix-ui/react-context-menu": "^2.2.16",
|
|
55
60
|
"@radix-ui/react-dialog": "^1.1.15",
|
|
56
61
|
"@radix-ui/react-dropdown-menu": "^2.1.16",
|
|
57
62
|
"@radix-ui/react-scroll-area": "^1.2.10",
|
|
@@ -59,7 +64,7 @@
|
|
|
59
64
|
"class-variance-authority": "^0.7.1",
|
|
60
65
|
"clsx": "^2.1.1",
|
|
61
66
|
"tailwind-merge": "^3.3.1",
|
|
62
|
-
"@bug-on/md3-tokens": "
|
|
67
|
+
"@bug-on/md3-tokens": "3.0.0"
|
|
63
68
|
},
|
|
64
69
|
"devDependencies": {
|
|
65
70
|
"@testing-library/jest-dom": "^6.9.1",
|
|
@@ -68,16 +73,15 @@
|
|
|
68
73
|
"@types/react": "^19.0.0",
|
|
69
74
|
"@types/react-dom": "^19.0.0",
|
|
70
75
|
"@vitejs/plugin-react": "^6.0.1",
|
|
76
|
+
"@vitest/coverage-v8": "4.1.4",
|
|
71
77
|
"jsdom": "^29.0.0",
|
|
72
78
|
"tsup": "^8.4.0",
|
|
73
79
|
"typescript": "5.8.3",
|
|
74
80
|
"vitest": "^4.1.0"
|
|
75
81
|
},
|
|
76
82
|
"scripts": {
|
|
77
|
-
"build": "tsup
|
|
83
|
+
"build": "tsup",
|
|
78
84
|
"dev": "tsup --watch",
|
|
79
|
-
"test": "vitest run",
|
|
80
|
-
"lint": "tsc --noEmit",
|
|
81
85
|
"clean": "rm -rf dist"
|
|
82
86
|
}
|
|
83
87
|
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
const fs = require("node:fs");
|
|
2
|
+
const path = require("node:path");
|
|
3
|
+
|
|
4
|
+
const srcAssets = path.join(__dirname, "../src/assets");
|
|
5
|
+
const distAssets = path.join(__dirname, "../dist/assets");
|
|
6
|
+
const srcCss = path.join(__dirname, "../src/ui/typography/typography.css");
|
|
7
|
+
const distCss = path.join(__dirname, "../dist/typography.css");
|
|
8
|
+
const srcIndexCss = path.join(__dirname, "../src/index.css");
|
|
9
|
+
const distIndexCss = path.join(__dirname, "../dist/index.css");
|
|
10
|
+
|
|
11
|
+
console.log("Copying assets to dist...");
|
|
12
|
+
|
|
13
|
+
if (fs.existsSync(srcAssets)) {
|
|
14
|
+
fs.cpSync(srcAssets, distAssets, { recursive: true });
|
|
15
|
+
console.log("✅ Copied src/assets to dist/assets");
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (fs.existsSync(srcCss)) {
|
|
19
|
+
let cssContent = fs.readFileSync(srcCss, "utf-8");
|
|
20
|
+
// Update font URL to be relative to the dist root
|
|
21
|
+
cssContent = cssContent.replace(
|
|
22
|
+
/url\(['"']?\.\.\/\.\.\/assets\/fonts\/GoogleSansFlex-VariableFont\.woff2['"']?\)/g,
|
|
23
|
+
"url('./assets/fonts/GoogleSansFlex-VariableFont.woff2')",
|
|
24
|
+
);
|
|
25
|
+
fs.writeFileSync(distCss, cssContent);
|
|
26
|
+
console.log("✅ Copied typography.css to dist/typography.css");
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (fs.existsSync(srcIndexCss)) {
|
|
30
|
+
fs.copyFileSync(srcIndexCss, distIndexCss);
|
|
31
|
+
console.log("✅ Copied index.css to dist/index.css");
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Copy Material Symbols CSS variants
|
|
35
|
+
const cssVariants = [
|
|
36
|
+
"material-symbols-cdn.css",
|
|
37
|
+
"material-symbols-self-hosted.css",
|
|
38
|
+
];
|
|
39
|
+
|
|
40
|
+
for (const file of cssVariants) {
|
|
41
|
+
const srcPath = path.join(__dirname, `../src/assets/${file}`);
|
|
42
|
+
const distPath = path.join(__dirname, `../dist/${file}`);
|
|
43
|
+
if (fs.existsSync(srcPath)) {
|
|
44
|
+
fs.copyFileSync(srcPath, distPath);
|
|
45
|
+
console.log(`✅ Copied ${file} to dist/${file}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Generate .d.ts stubs for each CSS sub-path export
|
|
50
|
+
// Satisfies the `types` field in exports — prevents "Cannot find module"
|
|
51
|
+
// errors in TypeScript strict mode projects.
|
|
52
|
+
const cssStubs = [
|
|
53
|
+
"index.css.d.ts",
|
|
54
|
+
"typography.css.d.ts",
|
|
55
|
+
"material-symbols-cdn.css.d.ts",
|
|
56
|
+
"material-symbols-self-hosted.css.d.ts",
|
|
57
|
+
];
|
|
58
|
+
|
|
59
|
+
for (const stub of cssStubs) {
|
|
60
|
+
const distPath = path.join(__dirname, `../dist/${stub}`);
|
|
61
|
+
fs.writeFileSync(distPath, "// CSS module — no runtime types\nexport {};\n");
|
|
62
|
+
console.log(`✅ Generated ${stub}`);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Prepend "use client" to JS/MJS output files to support React Server Components
|
|
66
|
+
const distFiles = [
|
|
67
|
+
path.join(__dirname, "../dist/index.js"),
|
|
68
|
+
path.join(__dirname, "../dist/index.mjs"),
|
|
69
|
+
];
|
|
70
|
+
|
|
71
|
+
for (const file of distFiles) {
|
|
72
|
+
if (fs.existsSync(file)) {
|
|
73
|
+
const content = fs.readFileSync(file, "utf-8");
|
|
74
|
+
if (
|
|
75
|
+
!content.startsWith('"use client";') &&
|
|
76
|
+
!content.startsWith("'use client';")
|
|
77
|
+
) {
|
|
78
|
+
fs.writeFileSync(file, `"use client";\n${content}`);
|
|
79
|
+
console.log(`✅ Prepended "use client" to ${path.basename(file)}`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<svg width="100%" height="100%" viewBox="4 4 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path fill="#D0BCFF">
|
|
3
|
+
<animate attributeName="d" dur="5s" repeatCount="indefinite" calcMode="spline" keySplines="0.5 0.2 0 0.8; 0.5 0.2 0 0.8; 0.5 0.2 0 0.8; 0.5 0.2 0 0.8; 0.5 0.2 0 0.8; 0.5 0.2 0 0.8; 0.5 0.2 0 0.8; 0.5 0.2 0 0.8; 0.5 0.2 0 0.8; 0.5 0.2 0 0.8; 0.5 0.2 0 0.8; 0.5 0.2 0 0.8; 0.5 0.2 0 0.8" keyTimes="0; 0.14; 0.14; 0.29; 0.29; 0.43; 0.43; 0.57; 0.57; 0.71; 0.71; 0.86; 0.86; 1" values="M20.9 10.4 21.4 9.5 21.9 8.7 22.5 7.8 23.2 7.2 24.2 7 25.1 7.4 25.7 8.1 26.2 9 26.8 9.8 27.3 10.6 28.1 11.2 29 11.3 30 11 30.9 10.6 31.8 10.3 32.8 9.9 33.7 10 34.5 10.6 34.9 11.5 34.8 12.5 34.8 13.5 34.7 14.5 34.7 15.5 35.2 16.3 36 16.8 37 17.1 37.9 17.3 38.9 17.5 39.8 17.9 40.4 18.7 40.5 19.7 40 20.5 39.4 21.3 38.7 22 38.1 22.8 37.6 23.7 37.7 24.6 38.3 25.5 38.9 26.2 39.6 27 40.2 27.7 40.5 28.7 40.3 29.6 39.5 30.3 38.6 30.6 37.6 30.8 36.7 31 35.7 31.3 35 31.9 34.6 32.8 34.7 33.8 34.8 34.8 34.9 35.8 34.8 36.8 34.3 37.6 33.4 38.1 32.4 38 31.5 37.6 30.6 37.2 29.7 36.9 28.7 36.6 27.8 36.9 27.1 37.6 26.6 38.5 26.1 39.3 25.5 40.2 24.8 40.8 23.8 41 22.9 40.6 22.3 39.9 21.8 39 21.2 38.2 20.7 37.4 19.9 36.8 19 36.7 18 37 17.1 37.4 16.2 37.7 15.2 38.1 14.3 38 13.5 37.4 13.1 36.5 13.2 35.5 13.2 34.5 13.3 33.5 13.3 32.5 12.8 31.7 12 31.2 11 31 10.1 30.7 9.1 30.5 8.2 30.1 7.6 29.3 7.5 28.3 8 27.5 8.7 26.7 9.3 26 9.9 25.2 10.4 24.3 10.3 23.4 9.7 22.5 9.1 21.8 8.4 21 7.8 20.3 7.5 19.3 7.7 18.4 8.5 17.7 9.4 17.4 10.4 17.2 11.3 17 12.3 16.7 13 16.1 13.4 15.2 13.3 14.2 13.2 13.2 13.1 12.2 13.2 11.2 13.7 10.4 14.6 9.9 15.6 10 16.5 10.4 17.4 10.8 18.3 11.1 19.3 11.4 20.2 11.1Z;
|
|
4
|
+
M20.3 8.6 21.1 8 22 7.6 23 7.3 23 7.3 24 7.2 25 7.3 25.9 7.5 26.8 8 27.6 8.6 28.4 9.1 28.4 9.1 29.3 9.6 30.3 9.8 31.3 9.9 32.3 10 33.3 10.2 34.2 10.6 34.2 10.6 35 11.2 35.7 11.9 36.3 12.7 36.7 13.6 36.9 14.6 37.2 15.5 37.2 15.5 37.6 16.5 38.2 17.3 38.9 18 39.6 18.7 40.2 19.5 40.6 20.4 40.6 20.4 40.9 21.3 41 22.3 40.9 23.3 40.6 24.3 40.2 25.2 39.8 26.1 39.8 26.1 39.5 27 39.4 28 39.5 29 39.6 30 39.5 31 39.3 32 39.3 32 38.9 32.9 38.3 33.7 37.6 34.4 36.8 35 35.9 35.4 35 35.8 35 35.8 34.1 36.3 33.4 37 32.9 37.9 32.3 38.7 31.6 39.4 30.8 40 30.8 40 29.9 40.4 28.9 40.7 27.9 40.8 27 40.7 26 40.4 25 40.1 25 40.1 24 40 23 40.1 22.1 40.4 21.1 40.7 20.1 40.8 19.1 40.7 19.1 40.7 18.2 40.5 17.3 40 16.4 39.5 15.7 38.8 15.2 37.9 14.6 37.1 14.6 37.1 13.9 36.4 13.1 35.8 12.2 35.4 11.3 35 10.5 34.4 9.7 33.8 9.7 33.8 9.1 32.9 8.7 32 8.5 31.1 8.4 30.1 8.5 29.1 8.6 28.1 8.6 28.1 8.5 27.1 8.3 26.1 7.8 25.2 7.4 24.3 7.1 23.4 7 22.4 7 22.4 7.1 21.4 7.3 20.4 7.8 19.5 8.3 18.7 9.1 18 9.8 17.3 9.8 17.3 10.4 16.5 10.8 15.6 11 14.6 11.3 13.7 11.7 12.8 12.2 11.9 12.2 11.9 12.9 11.2 13.8 10.7 14.7 10.2 15.6 10 16.6 9.9 17.6 9.8 17.6 9.8 18.6 9.6 19.5 9.2Z;
|
|
5
|
+
M18.6 9.6 19.5 9.2 20.3 8.6 21.1 8 22 7.6 23 7.3 24 7.2 25 7.3 25.9 7.5 26.8 8 27.6 8.6 28.4 9.1 29.3 9.6 30.3 9.8 31.3 9.9 32.3 10 33.3 10.2 34.2 10.6 35 11.2 35.7 11.9 36.3 12.7 36.7 13.6 36.9 14.6 37.2 15.5 37.6 16.4 38.2 17.3 38.9 18 39.6 18.7 40.2 19.5 40.6 20.4 40.9 21.3 41 22.3 40.9 23.3 40.6 24.3 40.2 25.2 39.8 26.1 39.5 27 39.4 28 39.5 29 39.6 30 39.5 31 39.3 32 38.9 32.9 38.3 33.7 37.6 34.4 36.8 35 35.9 35.4 35 35.8 34.1 36.3 33.4 37 32.9 37.9 32.3 38.7 31.6 39.4 30.8 40 29.9 40.4 28.9 40.7 27.9 40.8 27 40.7 26 40.4 25 40.1 24 40 23 40.1 22.1 40.4 21.1 40.7 20.1 40.8 19.1 40.7 18.2 40.5 17.3 40 16.4 39.5 15.7 38.8 15.2 37.9 14.6 37.1 13.9 36.4 13.1 35.8 12.2 35.4 11.3 35 10.5 34.4 9.7 33.8 9.1 32.9 8.7 32 8.5 31.1 8.4 30.1 8.5 29.1 8.6 28.1 8.5 27.1 8.3 26.1 7.8 25.2 7.4 24.3 7.1 23.4 7 22.4 7.1 21.4 7.3 20.4 7.8 19.5 8.3 18.7 9.1 18 9.8 17.3 10.4 16.5 10.8 15.6 11 14.6 11.3 13.7 11.7 12.8 12.2 11.9 12.9 11.2 13.8 10.7 14.7 10.2 15.6 10 16.6 9.9 17.6 9.8Z;
|
|
6
|
+
M18.6 9.9 19.5 9.4 20.3 8.8 21.1 8.2 22 7.8 23 7.6 23.9 7.5 24.9 7.6 25.9 7.8 26.8 8.2 27.6 8.7 28.5 9.3 29.3 9.9 30.1 10.5 30.9 11 31.7 11.6 32.5 12.2 33.3 12.8 33.7 13.1 34.1 13.3 34.9 13.9 35.7 14.5 36.6 15 37.4 15.6 38.2 16.2 39 16.8 39.7 17.5 40.2 18.3 40.7 19.2 40.9 20.1 41 21.1 40.9 22.1 40.7 23.1 40.3 24 40 24.9 39.7 25.9 39.4 26.8 39 27.8 38.7 28.7 38.4 29.6 38.1 30.6 37.8 31.5 37.5 32.5 37.2 33.4 36.9 34.4 36.6 35.3 36.2 36.2 35.7 37.1 35 37.8 34.3 38.4 33.4 38.9 32.5 39.3 31.5 39.5 30.5 39.5 30 39.5 29.5 39.5 28.5 39.5 27.5 39.5 26.5 39.5 25.5 39.4 24.5 39.4 23.6 39.4 22.6 39.4 21.6 39.5 20.6 39.5 19.6 39.5 18.6 39.5 17.6 39.5 16.6 39.5 15.6 39.3 14.7 39 13.8 38.5 13.1 37.9 12.4 37.2 11.9 36.3 11.5 35.4 11.2 34.5 10.9 33.5 10.6 32.6 10.3 31.6 10 30.7 9.7 29.7 9.3 28.8 9 27.9 8.7 26.9 8.4 26 8 25 7.7 24.1 7.4 23.2 7.1 22.2 7.1 21.7 7 21.2 7.1 20.2 7.3 19.3 7.7 18.4 8.3 17.5 8.9 16.8 9.7 16.2 10.5 15.6 11.4 15.1 12.2 14.5 13 14 13.8 13.4 14.6 12.8 15.4 12.3 16.2 11.7 17 11.1 17.8 10.5Z;
|
|
7
|
+
M15.4 12.3 16.2 11.7 17 11.1 17.8 10.5 18.6 9.9 19.5 9.4 20.3 8.8 21.1 8.3 22 7.8 23 7.6 23.9 7.5 24.9 7.6 25.9 7.8 26.8 8.2 27.6 8.7 28.5 9.3 29.3 9.9 30.1 10.5 30.9 11 31.7 11.6 32.5 12.2 33.3 12.8 34.1 13.3 34.9 13.9 35.7 14.5 36.6 15 37.4 15.6 38.2 16.2 39 16.8 39.7 17.5 40.2 18.3 40.7 19.2 40.9 20.1 41 21.1 40.9 22.1 40.7 23.1 40.3 24 40 24.9 39.7 25.9 39.4 26.8 39 27.8 38.7 28.7 38.4 29.6 38.1 30.6 37.8 31.5 37.5 32.5 37.2 33.4 36.9 34.4 36.6 35.3 36.2 36.2 35.7 37.1 35 37.8 34.3 38.4 33.4 38.9 32.5 39.3 31.5 39.4 30.5 39.5 29.5 39.5 28.5 39.5 27.5 39.5 26.5 39.5 25.5 39.4 24.5 39.4 23.6 39.4 22.6 39.4 21.6 39.5 20.6 39.5 19.6 39.5 18.6 39.5 17.6 39.5 16.6 39.5 15.6 39.3 14.7 39 13.8 38.5 13.1 37.9 12.4 37.2 11.9 36.3 11.5 35.4 11.2 34.5 10.9 33.5 10.6 32.6 10.3 31.6 10 30.7 9.7 29.7 9.3 28.8 9 27.9 8.7 26.9 8.4 26 8 25 7.7 24.1 7.4 23.2 7.1 22.2 7 21.2 7.1 20.2 7.3 19.3 7.7 18.4 8.3 17.5 8.9 16.8 9.7 16.2 10.5 15.6 11.4 15.1 12.2 14.5 13 14 13.8 13.4 14.6 12.8Z;
|
|
8
|
+
M17 12.8 17.7 12.1 18.5 11.5 19.3 10.9 20.1 10.5 20.2 10.4 21.1 10 22 9.7 23 9.4 24 9.2 25 9 26 9 27 9 27.6 9.1 28 9.1 28.9 9.3 29.9 9.6 30.9 9.9 31.8 10.3 32.6 10.8 33.5 11.3 34.3 11.9 34.6 12.2 35 12.6 35.7 13.3 36.4 14.1 36.9 14.9 37.4 15.8 37.9 16.6 38.3 17.6 38.6 18.5 38.6 18.7 38.8 19.5 38.9 20.5 39 21.5 39 22.5 38.9 23.5 38.7 24.5 38.5 25.4 38.2 26.3 38.2 26.4 37.8 27.3 37.4 28.2 36.8 29.1 36.2 29.9 35.6 30.6 34.9 31.3 34.2 32 33.8 32.5 33.5 32.8 32.8 33.5 32.1 34.2 31.4 34.9 30.7 35.6 29.9 36.2 29.1 36.8 28.2 37.3 27.9 37.5 27.4 37.8 26.4 38.2 25.5 38.5 24.5 38.7 23.5 38.9 22.5 39 21.5 39 20.5 38.9 20.4 38.9 19.5 38.8 18.6 38.6 17.6 38.3 16.7 37.9 15.8 37.5 14.9 37 14.1 36.4 13.4 35.8 13.3 35.8 12.6 35.1 12 34.3 11.3 33.5 10.8 32.7 10.3 31.8 9.9 30.9 9.6 30 9.4 29.3 9.3 29 9.1 28 9 27 9 26 9 25 9.2 24 9.4 23 9.6 22.1 9.8 21.7 10 21.1 10.4 20.2 10.9 19.4 11.4 18.5 12.1 17.8 12.7 17 13.4 16.3 14.2 15.6 14.2 15.5 14.9 14.9 15.6 14.2 16.3 13.5Z;
|
|
9
|
+
M33.5 11.3 34.3 11.9 35 12.6 35.3 12.8 35.7 13.3 36.4 14.1 36.9 14.9 37.4 15.8 37.9 16.6 38.3 17.6 38.3 17.7 38.6 18.5 38.8 19.5 38.9 20.5 39 21.5 39 22.5 38.9 23.5 38.9 23.5 38.7 24.5 38.5 25.4 38.2 26.4 37.8 27.3 37.4 28.2 36.9 28.9 36.8 29.1 36.2 29.9 35.6 30.6 34.9 31.3 34.2 32 33.5 32.8 33.1 33.2 32.8 33.5 32.1 34.2 31.4 34.9 30.7 35.6 29.9 36.2 29.1 36.8 28.7 37 28.2 37.3 27.4 37.8 26.4 38.2 25.5 38.5 24.5 38.7 23.5 38.9 23.3 38.9 22.5 39 21.5 39 20.5 38.9 19.5 38.8 18.6 38.6 17.6 38.3 17.6 38.3 16.7 37.9 15.8 37.5 14.9 37 14.1 36.4 13.3 35.8 12.7 35.2 12.6 35.1 12 34.3 11.3 33.5 10.8 32.7 10.3 31.8 9.9 30.9 9.7 30.3 9.6 29.9 9.3 29 9.1 28 9 27 9 26 9 25 9.1 24.5 9.2 24 9.4 23 9.6 22.1 10 21.1 10.4 20.2 10.9 19.4 11.1 19.1 11.5 18.5 12.1 17.7 12.7 17 13.5 16.3 14.2 15.6 14.9 14.9 14.9 14.8 15.6 14.2 16.3 13.5 17 12.8 17.7 12.1 18.5 11.5 19.3 11 19.3 10.9 20.2 10.4 21.1 10 22 9.7 23 9.4 24 9.2 24.7 9.1 25 9 26 9 27 9 28 9.1 28.9 9.3 29.9 9.6 30.4 9.7 30.9 9.9 31.8 10.3 32.6 10.8Z;
|
|
10
|
+
M33.2 11.1 34.2 11.2 35.1 11.4 36 11.9 36.6 12.7 36.8 13.7 36.9 14.7 36.9 15.7 37 16.7 37.1 17.7 37.3 18.6 37.9 19.4 38.5 20.2 39.2 20.9 39.8 21.7 40.5 22.4 40.9 23.3 41 24.3 40.7 25.2 40.1 26 39.4 26.8 38.8 27.5 38.1 28.3 37.5 29.1 37.1 30 37 31 37 31.9 36.9 32.9 36.8 33.9 36.7 34.9 36.2 35.8 35.5 36.4 34.5 36.8 33.6 36.8 32.6 36.9 31.6 37 30.6 37.1 29.6 37.2 28.8 37.7 28 38.4 27.3 39 26.5 39.7 25.8 40.3 24.9 40.8 23.9 41 23 40.8 22.1 40.2 21.4 39.6 20.6 38.9 19.9 38.3 19.1 37.6 18.3 37.2 17.3 37 16.3 37 15.3 36.9 14.3 36.8 13.3 36.7 12.4 36.4 11.7 35.7 11.3 34.8 11.2 33.8 11.1 32.8 11 31.8 11 30.8 10.9 29.9 10.4 29 9.8 28.2 9.1 27.5 8.5 26.7 7.8 26 7.3 25.1 7 24.2 7.1 23.2 7.6 22.3 8.2 21.6 8.9 20.8 9.5 20.1 10.2 19.3 10.7 18.5 10.9 17.5 11 16.6 11.1 15.6 11.1 14.6 11.2 13.6 11.5 12.6 12.1 11.9 13 11.4 13.9 11.2 14.9 11.1 15.9 11 16.9 11 17.9 10.9 18.8 10.6 19.6 10 20.4 9.3 21.1 8.6 21.9 8 22.6 7.4 23.6 7 24.6 7.1 25.5 7.5 26.2 8.1 27 8.7 27.7 9.4 28.5 10 29.3 10.6 30.2 10.9 31.2 11 32.2 11.1Z;
|
|
11
|
+
M27.7 9.4 28.5 10 29.3 10.6 30.2 10.9 31.2 11 32.2 11.1 33.2 11.1 34.2 11.2 35.1 11.4 36 11.9 36.6 12.7 36.8 13.7 36.9 14.7 36.9 15.7 37 16.7 37.1 17.7 37.3 18.6 37.9 19.4 38.5 20.2 39.2 20.9 39.8 21.7 40.5 22.4 40.9 23.3 41 24.3 40.7 25.2 40.1 26 39.4 26.8 38.8 27.5 38.1 28.3 37.5 29.1 37.1 30 37 31 37 31.9 36.9 32.9 36.8 33.9 36.7 34.9 36.2 35.8 35.5 36.4 34.5 36.8 33.6 36.9 32.6 36.9 31.6 37 30.6 37.1 29.6 37.2 28.8 37.7 28 38.4 27.3 39 26.5 39.7 25.8 40.3 24.9 40.8 23.9 41 23 40.8 22.1 40.2 21.4 39.6 20.6 38.9 19.9 38.3 19.1 37.6 18.3 37.2 17.3 37 16.3 37 15.3 36.9 14.3 36.8 13.3 36.7 12.4 36.4 11.7 35.7 11.3 34.8 11.2 33.8 11.1 32.8 11 31.8 11 30.8 10.9 29.9 10.4 29 9.8 28.2 9.1 27.5 8.5 26.7 7.8 26 7.3 25.1 7 24.2 7.1 23.2 7.6 22.3 8.2 21.6 8.9 20.8 9.5 20.1 10.2 19.3 10.7 18.5 10.9 17.5 11 16.5 11.1 15.6 11.1 14.6 11.2 13.6 11.5 12.6 12.1 11.9 13 11.4 13.9 11.2 14.9 11.1 15.9 11 16.9 11 17.9 10.9 18.8 10.6 19.6 10 20.4 9.3 21.1 8.6 21.9 8 22.6 7.4 23.6 7 24.6 7.1 25.5 7.5 26.2 8.1 27 8.7Z;
|
|
12
|
+
M27.9 10.6 28.8 10.3 29.8 10.1 30.8 10 31.8 10.1 32.7 10.3 33.7 10.6 34.6 11.1 34.8 11.3 35.4 11.7 36.1 12.4 36.7 13.1 37.2 14 37.6 14.9 37.9 15.9 38 16.9 38 17.9 37.8 18.8 37.5 19.8 37.1 20.7 36.8 21.6 36.5 22.6 36.4 23.6 36.4 24.4 36.4 24.6 36.5 25.5 36.8 26.5 37.2 27.4 37.6 28.3 37.8 29.3 38 30.3 38 31.3 37.8 32.3 37.6 33.2 37.2 34.1 36.6 35 36 35.7 35.3 36.4 34.4 37 34.1 37.2 33.6 37.4 32.6 37.8 31.6 37.9 30.6 38 29.7 37.9 28.7 37.7 27.8 37.3 26.8 36.9 25.9 36.6 24.9 36.4 23.9 36.4 22.9 36.4 22 36.6 21 37 20.1 37.4 20.1 37.4 19.2 37.7 18.2 37.9 17.2 38 16.2 37.9 15.3 37.7 14.3 37.4 13.4 36.9 12.6 36.3 11.9 35.6 11.3 34.9 10.8 34 10.4 33.1 10.1 32.1 10 31.1 10 30.6 10 30.1 10.2 29.2 10.5 28.2 10.9 27.3 11.2 26.4 11.5 25.4 11.6 24.4 11.6 23.4 11.5 22.5 11.2 21.5 10.8 20.6 10.4 19.7 10.2 18.7 10 17.7 10 16.7 10 16.6 10.2 15.7 10.4 14.8 10.8 13.9 11.4 13 12 12.3 12.7 11.6 13.6 11 14.4 10.6 15.4 10.2 16.4 10.1 17.4 10 18.3 10.1 19.3 10.3 20.2 10.7 20.9 11 21.2 11.1 22.1 11.4 23.1 11.6 24.1 11.6 25.1 11.6 26 11.4 27 11Z;
|
|
13
|
+
M36 35.7 35.3 36.4 34.4 37 33.6 37.4 32.6 37.8 31.6 37.9 30.6 38 29.7 37.9 28.7 37.7 27.8 37.3 26.8 36.9 25.9 36.6 24.9 36.4 23.9 36.4 22.9 36.4 22 36.6 21 37 20.1 37.4 19.2 37.7 18.2 37.9 17.2 38 16.2 37.9 15.3 37.7 14.3 37.4 13.4 36.9 12.6 36.3 11.9 35.6 11.3 34.9 10.8 34 10.4 33.1 10.1 32.1 10 31.1 10 30.2 10.2 29.2 10.5 28.2 10.9 27.3 11.2 26.4 11.5 25.4 11.6 24.4 11.6 23.4 11.5 22.5 11.2 21.5 10.8 20.6 10.4 19.7 10.2 18.7 10 17.7 10 16.7 10.2 15.7 10.4 14.8 10.8 13.9 11.4 13 12 12.3 12.7 11.6 13.6 11 14.4 10.6 15.4 10.2 16.4 10.1 17.4 10 18.3 10.1 19.3 10.3 20.2 10.7 21.2 11.1 22.1 11.4 23.1 11.6 24.1 11.6 25.1 11.6 26 11.4 27 11 27.9 10.6 28.8 10.3 29.8 10.1 30.8 10 31.8 10.1 32.7 10.3 33.7 10.6 34.6 11.1 35.4 11.7 36.1 12.4 36.7 13.1 37.2 14 37.6 14.9 37.9 15.9 38 16.9 38 17.8 37.8 18.8 37.5 19.8 37.1 20.7 36.8 21.6 36.5 22.6 36.4 23.6 36.4 24.6 36.5 25.5 36.8 26.5 37.2 27.4 37.6 28.3 37.8 29.3 38 30.3 38 31.3 37.8 32.3 37.6 33.2 37.2 34.1 36.6 35Z;
|
|
14
|
+
M32.1 32.1 31.4 32.8 30.7 33.5 29.9 34.1 29.1 34.7 28.3 35.3 27.6 35.8 27.5 35.8 26.6 36.4 25.8 36.8 24.9 37.3 24 37.7 23.1 38 22.1 38.3 21.2 38.6 20.2 38.8 19.2 38.9 18.2 39 17.2 39 16.6 38.9 16.3 38.9 15.3 38.7 14.3 38.4 13.4 38 12.5 37.5 11.7 36.9 11.1 36.3 10.5 35.5 10 34.6 9.6 33.7 9.3 32.7 9.1 31.7 9.1 31.4 9 30.8 9 29.8 9.1 28.8 9.2 27.8 9.4 26.8 9.7 25.9 10 24.9 10.3 24 10.7 23.1 11.2 22.2 11.6 21.4 12.2 20.5 12.2 20.4 12.7 19.7 13.3 18.9 13.9 18.1 14.5 17.3 15.2 16.6 15.9 15.9 16.6 15.2 17.3 14.5 18.1 13.9 18.9 13.3 19.7 12.7 20.4 12.2 20.5 12.2 21.4 11.6 22.2 11.2 23.1 10.7 24 10.3 24.9 10 25.9 9.7 26.8 9.4 27.8 9.2 28.8 9.1 29.8 9 30.8 9 31.4 9.1 31.7 9.1 32.7 9.3 33.7 9.6 34.6 10 35.5 10.5 36.3 11.1 36.9 11.7 37.5 12.5 38 13.4 38.4 14.3 38.7 15.3 38.9 16.3 38.9 16.6 39 17.2 39 18.2 38.9 19.2 38.8 20.2 38.6 21.2 38.3 22.1 38 23.1 37.7 24 37.3 24.9 36.8 25.8 36.4 26.6 35.8 27.5 35.8 27.6 35.3 28.3 34.7 29.1 34.1 29.9 33.5 30.7 32.8 31.4Z;
|
|
15
|
+
M24.3 10.2 24.9 10 25.9 9.7 26.8 9.4 27.1 9.4 27.8 9.2 28.8 9.1 29.8 9 29.9 9 30.8 9 31.7 9.1 32.7 9.3 32.8 9.3 33.7 9.6 34.6 10 35.5 10.5 35.5 10.5 36.3 11.1 36.9 11.7 37.5 12.5 37.5 12.5 38 13.4 38.4 14.3 38.7 15.2 38.7 15.3 38.9 16.3 39 17.2 39 18.1 39 18.2 38.9 19.2 38.8 20.2 38.6 20.9 38.6 21.2 38.3 22.1 38 23.1 37.8 23.7 37.7 24 37.3 24.9 36.8 25.8 36.5 26.4 36.4 26.6 35.8 27.5 35.3 28.3 35 28.8 34.7 29.1 34.1 29.9 33.5 30.7 33.1 31.1 32.8 31.4 32.1 32.1 31.4 32.8 31.1 33.1 30.7 33.5 29.9 34.1 29.1 34.7 28.8 35 28.3 35.3 27.5 35.8 26.6 36.4 26.4 36.5 25.8 36.8 24.9 37.3 24 37.7 23.7 37.8 23.1 38 22.1 38.3 21.2 38.6 20.9 38.6 20.2 38.8 19.2 38.9 18.2 39 18.1 39 17.2 39 16.3 38.9 15.3 38.7 15.2 38.7 14.3 38.4 13.4 38 12.5 37.5 12.5 37.5 11.7 36.9 11.1 36.3 10.5 35.5 10.5 35.5 10 34.6 9.6 33.7 9.3 32.8 9.3 32.7 9.1 31.7 9 30.8 9 29.9 9 29.8 9.1 28.8 9.2 27.8 9.4 27.1 9.4 26.8 9.7 25.9 10 24.9 10.2 24.3 10.3 24 10.7 23.1 11.2 22.2 11.5 21.6 11.6 21.4 12.2 20.5 12.7 19.7 13 19.2 13.3 18.9 13.9 18.1 14.5 17.3 14.9 16.9 15.2 16.6 15.9 15.9 16.6 15.2 16.9 14.9 17.3 14.5 18.1 13.9 18.9 13.3 19.2 13 19.7 12.7 20.5 12.2 21.4 11.6 21.6 11.5 22.2 11.2 23.1 10.7 24 10.3Z;
|
|
16
|
+
M22.5 7.8 23.2 7.2 24.2 7 25.1 7.4 25.7 8.1 26.2 9 26.8 9.8 27.3 10.6 28.1 11.2 29 11.3 30 11 30.9 10.6 31.8 10.3 32.8 9.9 33.7 10 34.5 10.6 34.9 11.5 34.8 12.5 34.8 13.5 34.7 14.5 34.7 15.5 35.2 16.3 36 16.8 37 17 37.9 17.3 38.9 17.5 39.8 17.9 40.4 18.7 40.5 19.7 40 20.5 39.3 21.3 38.7 22 38.1 22.8 37.6 23.7 37.7 24.6 38.3 25.4 38.9 26.2 39.6 27 40.2 27.7 40.5 28.6 40.3 29.6 39.5 30.3 38.6 30.6 37.6 30.8 36.7 31 35.7 31.3 35 31.9 34.6 32.8 34.7 33.8 34.8 34.8 34.8 35.8 34.8 36.8 34.3 37.6 33.4 38.1 32.4 38 31.5 37.6 30.6 37.2 29.7 36.9 28.7 36.6 27.8 36.9 27.1 37.6 26.6 38.5 26.1 39.3 25.5 40.2 24.8 40.8 23.8 41 22.9 40.6 22.3 39.9 21.8 39 21.2 38.2 20.7 37.4 19.9 36.8 19 36.7 18 37 17.1 37.4 16.2 37.7 15.2 38.1 14.3 38 13.5 37.4 13.1 36.5 13.2 35.5 13.2 34.5 13.3 33.5 13.3 32.5 12.8 31.7 12 31.2 11 31 10.1 30.7 9.1 30.5 8.2 30.1 7.6 29.3 7.5 28.3 8 27.5 8.7 26.7 9.3 26 9.9 25.2 10.4 24.3 10.3 23.4 9.7 22.6 9.1 21.8 8.4 21 7.8 20.3 7.5 19.4 7.7 18.4 8.5 17.7 9.4 17.4 10.4 17.2 11.3 17 12.3 16.7 13 16.1 13.4 15.2 13.3 14.2 13.2 13.2 13.2 12.2 13.2 11.2 13.7 10.4 14.6 9.9 15.6 10 16.5 10.4 17.4 10.8 18.3 11.1 19.3 11.4 20.2 11.1 20.9 10.4 21.4 9.5 21.9 8.7Z"></animate>
|
|
17
|
+
<animateTransform attributeName="transform" attributeType="XML" type="rotate" dur="5s" repeatCount="indefinite" calcMode="spline" keySplines="0.5 0.2 0 0.8; 0.5 0.2 0 0.8; 0.5 0.2 0 0.8; 0.5 0.2 0 0.8; 0.5 0.2 0 0.8; 0.5 0.2 0 0.8; 0.5 0.2 0 0.8" keyTimes="0; 0.14; 0.29; 0.43; 0.57; 0.71; 0.86; 1" values="0 24 24; 154 24 24; 309 24 24; 463 24 24; 617 24 24; 771 24 24; 926 24 24; 1080 24 24"></animateTransform>
|
|
18
|
+
</path>
|
|
19
|
+
</svg>
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Material Symbols — CDN version (Google Fonts)
|
|
3
|
+
*
|
|
4
|
+
* USAGE IN APP'S HTML <head>:
|
|
5
|
+
* Add preconnect hints BEFORE this CSS loads for fastest performance:
|
|
6
|
+
*
|
|
7
|
+
* <link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
8
|
+
* <link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
|
|
9
|
+
*
|
|
10
|
+
* Then import this CSS:
|
|
11
|
+
* import '@bug-on/md3-react/material-symbols-cdn.css'
|
|
12
|
+
*
|
|
13
|
+
* WHY TWO preconnect?
|
|
14
|
+
* Google Fonts serves the CSS stylesheet from fonts.googleapis.com
|
|
15
|
+
* but the actual .woff2 font files come from fonts.gstatic.com (different origin).
|
|
16
|
+
* The crossorigin attribute is required for font files (CORS request).
|
|
17
|
+
*
|
|
18
|
+
* FONT-DISPLAY NOTE for icon fonts:
|
|
19
|
+
* We use font-display: block (NOT swap) because:
|
|
20
|
+
* - swap would briefly show raw text like "arrow_forward" before icon loads = jarring layout shift
|
|
21
|
+
* - block hides text during load period (max 3s), then shows icon = cleaner UX
|
|
22
|
+
* - optional is NOT suitable: if font misses the load window, icons never appear
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/*
|
|
26
|
+
* INSTRUCTION:
|
|
27
|
+
* Use the <MaterialSymbolsPreconnect /> component to load the actual Google Fonts CSS!
|
|
28
|
+
*
|
|
29
|
+
* We NO LONGER use @import url(...) here because CSS bundlers (like Next.js/Webpack)
|
|
30
|
+
* often merge global CSS files and push @import statements below regular CSS rules.
|
|
31
|
+
* According to CSS spec, any @import MUST be at the very top, so it breaks randomly.
|
|
32
|
+
* Loading via `<link rel="stylesheet">` (handled by MaterialSymbolsPreconnect) is fully robust.
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
/* ─────────────────────────────────────────────────────────────────────────────
|
|
36
|
+
* BASE ICON STYLES
|
|
37
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
38
|
+
*
|
|
39
|
+
* This class ensures that Material Symbols render correctly as ligatures
|
|
40
|
+
* across all browsers and prevents common layout issues.
|
|
41
|
+
*/
|
|
42
|
+
.md-icon {
|
|
43
|
+
font-family: inherit; /* Set dynamically by the Icon component */
|
|
44
|
+
font-weight: normal;
|
|
45
|
+
font-style: normal;
|
|
46
|
+
display: inline-flex;
|
|
47
|
+
align-items: center;
|
|
48
|
+
justify-content: center;
|
|
49
|
+
width: 1em;
|
|
50
|
+
height: 1em;
|
|
51
|
+
line-height: normal;
|
|
52
|
+
text-transform: none;
|
|
53
|
+
letter-spacing: normal;
|
|
54
|
+
word-wrap: normal;
|
|
55
|
+
white-space: nowrap;
|
|
56
|
+
direction: ltr;
|
|
57
|
+
|
|
58
|
+
/* Enable ligature rendering support for modern browsers */
|
|
59
|
+
font-feature-settings: "liga";
|
|
60
|
+
|
|
61
|
+
/* Improved rendering quality */
|
|
62
|
+
-webkit-font-smoothing: antialiased;
|
|
63
|
+
-moz-osx-font-smoothing: grayscale;
|
|
64
|
+
text-rendering: optimizeLegibility;
|
|
65
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Material Symbols — Self-Hosted version
|
|
3
|
+
*
|
|
4
|
+
* SETUP STEPS:
|
|
5
|
+
*
|
|
6
|
+
* Step 1 — Download font files
|
|
7
|
+
* Truy cập: https://github.com/google/material-design-icons/tree/master/variablefont
|
|
8
|
+
* Download file: MaterialSymbolsOutlined[FILL,GRAD,opsz,wght].woff2
|
|
9
|
+
* (và Rounded / Sharp nếu cần)
|
|
10
|
+
*
|
|
11
|
+
* Step 2 — Place font files in your app
|
|
12
|
+
* Recommended location: public/fonts/ hoặc src/assets/fonts/
|
|
13
|
+
* Example: public/fonts/MaterialSymbolsOutlined.woff2
|
|
14
|
+
*
|
|
15
|
+
* Step 3 — Copy và điều chỉnh @font-face block bên dưới
|
|
16
|
+
* Thay đổi src url() để trỏ đúng đường dẫn trong project của bạn
|
|
17
|
+
*
|
|
18
|
+
* Step 4 — Import file này:
|
|
19
|
+
* import '@bug-on/md3-react/material-symbols-self-hosted.css'
|
|
20
|
+
*
|
|
21
|
+
* PERFORMANCE NOTES:
|
|
22
|
+
* - Self-hosting tốt hơn CDN khi bạn dùng CDN + HTTP/2 cho static assets
|
|
23
|
+
* - Nếu không có CDN, Google Fonts CDN có thể nhanh hơn do cache sharing
|
|
24
|
+
* - Dùng font-display: block cho icon fonts (xem lý do ở file CDN)
|
|
25
|
+
* - WOFF2 là format duy nhất cần thiết (100% modern browser support, Brotli compression)
|
|
26
|
+
* - Không cần WOFF fallback nữa
|
|
27
|
+
*
|
|
28
|
+
* SUBSETTING (QUAN TRỌNG để giảm file size):
|
|
29
|
+
* Full variable font ~295 KB. Sau khi subset còn ~1-2 KB cho vài chục icons.
|
|
30
|
+
* Dùng tool: https://everythingfonts.com/subsetter
|
|
31
|
+
* Hoặc dùng Google Fonts text parameter để subset trên CDN:
|
|
32
|
+
* ?family=Material+Symbols+Outlined&text=home%20search%20settings
|
|
33
|
+
*
|
|
34
|
+
* GDPR NOTE:
|
|
35
|
+
* Self-hosting loại bỏ việc gửi user IP đến Google servers,
|
|
36
|
+
* giải quyết GDPR compliance requirement.
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
@font-face {
|
|
40
|
+
font-family: "Material Symbols Outlined";
|
|
41
|
+
font-style: normal;
|
|
42
|
+
/* Khai báo full axis range để browser biết đây là variable font */
|
|
43
|
+
font-weight: 100 700;
|
|
44
|
+
/* font-display: block là bắt buộc cho icon fonts:
|
|
45
|
+
* - Tránh render text thô "arrow_forward" thay vì icon
|
|
46
|
+
* - Max 3s block, sau đó icon xuất hiện
|
|
47
|
+
* Tham khảo: https://web.dev/articles/font-best-practices#icon_fonts */
|
|
48
|
+
font-display: block;
|
|
49
|
+
src: url("/fonts/MaterialSymbolsOutlined[FILL,GRAD,opsz,wght].woff2")
|
|
50
|
+
format("woff2");
|
|
51
|
+
/* unicode-range: chỉ load font khi page chứa ký tự trong range này.
|
|
52
|
+
* Material Symbols dùng PUA (Private Use Area) cho ligatures. */
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/*
|
|
56
|
+
* Rounded variants and Sharp variants are not included by default to save space.
|
|
57
|
+
* You can declare them similarly if you download the respective woff2 files.
|
|
58
|
+
*/
|
|
59
|
+
|
|
60
|
+
/* ─────────────────────────────────────────────────────────────────────────────
|
|
61
|
+
* BASE ICON STYLES
|
|
62
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
63
|
+
*
|
|
64
|
+
* This class ensures that Material Symbols render correctly as ligatures
|
|
65
|
+
* across all browsers and prevents common layout issues.
|
|
66
|
+
*/
|
|
67
|
+
.md-icon {
|
|
68
|
+
font-family: inherit; /* Set dynamically by the Icon component */
|
|
69
|
+
font-weight: normal;
|
|
70
|
+
font-style: normal;
|
|
71
|
+
display: inline-flex;
|
|
72
|
+
align-items: center;
|
|
73
|
+
justify-content: center;
|
|
74
|
+
width: 1em;
|
|
75
|
+
height: 1em;
|
|
76
|
+
line-height: normal;
|
|
77
|
+
text-transform: none;
|
|
78
|
+
letter-spacing: normal;
|
|
79
|
+
word-wrap: normal;
|
|
80
|
+
white-space: nowrap;
|
|
81
|
+
direction: ltr;
|
|
82
|
+
|
|
83
|
+
/* Enable ligature rendering support for modern browsers */
|
|
84
|
+
font-feature-settings: "liga";
|
|
85
|
+
|
|
86
|
+
/* Improved rendering quality */
|
|
87
|
+
-webkit-font-smoothing: antialiased;
|
|
88
|
+
-moz-osx-font-smoothing: grayscale;
|
|
89
|
+
text-rendering: optimizeLegibility;
|
|
90
|
+
}
|
package/src/css.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// CSS module type declarations for @bug-on/md3-react sub-path imports
|
|
2
|
+
declare module "@bug-on/md3-react/index.css" {
|
|
3
|
+
const styles: string;
|
|
4
|
+
export default styles;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
declare module "@bug-on/md3-react/typography.css" {
|
|
8
|
+
const styles: string;
|
|
9
|
+
export default styles;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
declare module "@bug-on/md3-react/material-symbols-cdn.css" {
|
|
13
|
+
const styles: string;
|
|
14
|
+
export default styles;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
declare module "@bug-on/md3-react/material-symbols-self-hosted.css" {
|
|
18
|
+
const styles: string;
|
|
19
|
+
export default styles;
|
|
20
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { useEffect, useRef } from "react";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Hook to detect clicks outside of a specified element.
|
|
5
|
+
*
|
|
6
|
+
* @param handler - Callback function to execute when a click outside occurs.
|
|
7
|
+
* @param enabled - Whether the listener is active.
|
|
8
|
+
* @returns A RefObject to be attached to the target element.
|
|
9
|
+
*/
|
|
10
|
+
export function useClickOutside<T extends HTMLElement>(
|
|
11
|
+
handler: () => void,
|
|
12
|
+
enabled = true,
|
|
13
|
+
) {
|
|
14
|
+
const ref = useRef<T>(null);
|
|
15
|
+
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
if (!enabled) return;
|
|
18
|
+
|
|
19
|
+
const listener = (event: MouseEvent | TouchEvent) => {
|
|
20
|
+
const el = ref.current;
|
|
21
|
+
if (!el || el.contains(event.target as Node)) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
handler();
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
document.addEventListener("mousedown", listener);
|
|
28
|
+
document.addEventListener("touchstart", listener);
|
|
29
|
+
|
|
30
|
+
return () => {
|
|
31
|
+
document.removeEventListener("mousedown", listener);
|
|
32
|
+
document.removeEventListener("touchstart", listener);
|
|
33
|
+
};
|
|
34
|
+
}, [handler, enabled]);
|
|
35
|
+
|
|
36
|
+
return ref;
|
|
37
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useEffect, useState } from "react";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* useMediaQuery — Responsive hook chuẩn SSR-safe
|
|
7
|
+
*
|
|
8
|
+
* Tránh hydration mismatch bằng cách khởi tạo với `false`.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```tsx
|
|
12
|
+
* const isMobile = useMediaQuery('(max-width: 768px)');
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export function useMediaQuery(query: string): boolean {
|
|
16
|
+
const [matches, setMatches] = useState(false);
|
|
17
|
+
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
const mql = window.matchMedia(query);
|
|
20
|
+
const handler = (e: MediaQueryListEvent) => setMatches(e.matches);
|
|
21
|
+
|
|
22
|
+
setMatches(mql.matches);
|
|
23
|
+
mql.addEventListener("change", handler);
|
|
24
|
+
return () => mql.removeEventListener("change", handler);
|
|
25
|
+
}, [query]);
|
|
26
|
+
|
|
27
|
+
return matches;
|
|
28
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { useCallback, useRef } from "react";
|
|
2
|
+
|
|
3
|
+
export interface RippleOptions {
|
|
4
|
+
/** Thời gian hiệu ứng ripple (ms). Mặc định: 600 */
|
|
5
|
+
duration?: number;
|
|
6
|
+
/** Màu ripple. Mặc định: 'currentColor' */
|
|
7
|
+
color?: string;
|
|
8
|
+
/** Opacity. Mặc định: 0.12 (chuẩn MD3) */
|
|
9
|
+
opacity?: number;
|
|
10
|
+
/** Tắt ripple (ví dụ khi disabled) */
|
|
11
|
+
disabled?: boolean;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* useRipple — Material Design 3 Expressive Ripple Effect
|
|
16
|
+
*
|
|
17
|
+
* Hook thuần DOM, không phụ thuộc thư viện animation ngoài.
|
|
18
|
+
* Chú ý: Yêu cầu element có `position: relative` và `overflow: hidden`.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```tsx
|
|
22
|
+
* const { rippleRef, onPointerDown } = useRipple();
|
|
23
|
+
* <button ref={rippleRef} onPointerDown={onPointerDown}>Click me</button>
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export function useRipple<T extends HTMLElement = HTMLElement>(
|
|
27
|
+
options: RippleOptions = {},
|
|
28
|
+
) {
|
|
29
|
+
const {
|
|
30
|
+
duration = 600,
|
|
31
|
+
color = "currentColor",
|
|
32
|
+
opacity = 0.12,
|
|
33
|
+
disabled = false,
|
|
34
|
+
} = options;
|
|
35
|
+
const ref = useRef<T>(null);
|
|
36
|
+
|
|
37
|
+
const onPointerDown = useCallback(
|
|
38
|
+
(event: React.PointerEvent<T>) => {
|
|
39
|
+
if (disabled || !ref.current) return;
|
|
40
|
+
|
|
41
|
+
const el = ref.current;
|
|
42
|
+
const rect = el.getBoundingClientRect();
|
|
43
|
+
|
|
44
|
+
const size = Math.max(rect.width, rect.height) * 2;
|
|
45
|
+
const x = event.clientX - rect.left - size / 2;
|
|
46
|
+
const y = event.clientY - rect.top - size / 2;
|
|
47
|
+
|
|
48
|
+
const ripple = document.createElement("span");
|
|
49
|
+
ripple.setAttribute("aria-hidden", "true");
|
|
50
|
+
|
|
51
|
+
Object.assign(ripple.style, {
|
|
52
|
+
position: "absolute",
|
|
53
|
+
borderRadius: "50%",
|
|
54
|
+
pointerEvents: "none",
|
|
55
|
+
width: `${size}px`,
|
|
56
|
+
height: `${size}px`,
|
|
57
|
+
left: `${x}px`,
|
|
58
|
+
top: `${y}px`,
|
|
59
|
+
background: color,
|
|
60
|
+
opacity: String(opacity),
|
|
61
|
+
transform: "scale(0)",
|
|
62
|
+
transition: `transform ${duration}ms cubic-bezier(0.2, 0, 0, 1), opacity ${duration * 0.6}ms ease-out`,
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
el.appendChild(ripple);
|
|
66
|
+
|
|
67
|
+
// Frame sau để trigger animation
|
|
68
|
+
requestAnimationFrame(() => {
|
|
69
|
+
ripple.style.transform = "scale(1)";
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
const cleanup = () => {
|
|
73
|
+
ripple.style.opacity = "0";
|
|
74
|
+
setTimeout(() => {
|
|
75
|
+
if (el.contains(ripple)) el.removeChild(ripple);
|
|
76
|
+
}, duration * 0.6);
|
|
77
|
+
el.removeEventListener("pointerup", cleanup);
|
|
78
|
+
el.removeEventListener("pointerleave", cleanup);
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
el.addEventListener("pointerup", cleanup, { once: true });
|
|
82
|
+
el.addEventListener("pointerleave", cleanup, { once: true });
|
|
83
|
+
},
|
|
84
|
+
[disabled, duration, color, opacity],
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
return { rippleRef: ref, onPointerDown };
|
|
88
|
+
}
|
package/src/index.css
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/* @bug-on/md3-react - Base Reset Styles */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Hide default browser UI elements that conflict with MD3 custom UI.
|
|
5
|
+
* - Hide search clear/decoration buttons in WebKit/Blink (Chrome, Safari, Edge).
|
|
6
|
+
* - Hide IE/Edge specific clear and reveal (password) buttons.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/* Hide default search clear button and related decorations */
|
|
10
|
+
input[type="search"]::-webkit-search-decoration,
|
|
11
|
+
input[type="search"]::-webkit-search-cancel-button,
|
|
12
|
+
input[type="search"]::-webkit-search-results-button,
|
|
13
|
+
input[type="search"]::-webkit-search-results-decoration {
|
|
14
|
+
-webkit-appearance: none;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/* Hide IE/Edge clear and reveal (password toggle) buttons */
|
|
18
|
+
input::-ms-clear,
|
|
19
|
+
input::-ms-reveal {
|
|
20
|
+
display: none;
|
|
21
|
+
width: 0;
|
|
22
|
+
height: 0;
|
|
23
|
+
}
|