@stacksjs/defaults 0.75.220 → 0.75.221

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.
@@ -92,7 +92,7 @@ Browser runtime bindings are documented separately in `stacks-auto-imports`.
92
92
  | `@stacksjs/tinker` | [`stacks-repl`](../stacks-repl/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/tinker/src/index.ts) | 1 |
93
93
  | `@stacksjs/tunnel` | [`stacks-tunnel`](../stacks-tunnel/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/tunnel/src/index.ts) | 1 |
94
94
  | `@stacksjs/types` | [`stacks-types`](../stacks-types/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/index.ts) | 2 |
95
- | `@stacksjs/ui` | [`stacks-ui`](../stacks-ui/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ui/src/index.ts) | 5 |
95
+ | `@stacksjs/ui` | [`stacks-ui`](../stacks-ui/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ui/src/index.ts) | 6 |
96
96
  | `@stacksjs/utils` | [`stacks-utils`](../stacks-utils/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/index.ts) | 15 |
97
97
  | `@stacksjs/validation` | [`stacks-validation`](../stacks-validation/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/validation/src/index.ts) | 17 |
98
98
  | `@stacksjs/video` | [`stacks-video`](../stacks-video/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/video/src/index.ts) | 3 |
@@ -889,7 +889,7 @@ Declared runtime exports: `CssEngine`, `buildPageSequence`, `paginatorVariant`,
889
889
 
890
890
  Local source modules: [src/fonts.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ui/src/fonts.ts), [src/pagination.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ui/src/pagination.ts).
891
891
 
892
- Evidence directory: [5 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ui/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
892
+ Evidence directory: [6 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ui/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
893
893
 
894
894
  ### @stacksjs/utils
895
895
 
@@ -2,7 +2,7 @@
2
2
  "publisher": "Stacks",
3
3
  "name": "vscode-stacks",
4
4
  "displayName": "Stacks",
5
- "version": "0.75.220",
5
+ "version": "0.75.221",
6
6
  "description": "Stacks, built into VS Code: stx templates, pickier linting and formatting, encrypted env files, the dev server preview and every buddy command. No other extensions required.",
7
7
  "license": "MIT",
8
8
  "funding": "https://github.com/sponsors/chrisbbreuer",
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@stacksjs/defaults",
3
3
  "type": "module",
4
4
  "sideEffects": false,
5
- "version": "0.75.220",
5
+ "version": "0.75.221",
6
6
  "repository": {
7
7
  "type": "git",
8
8
  "url": "git+https://github.com/stacksjs/stacks.git",
@@ -44,7 +44,7 @@
44
44
  "dependencies": {
45
45
  "@iconify-json/f7": "^1.2.2",
46
46
  "@iconify-json/hugeicons": "^1.2.35",
47
- "@stacksjs/mobile": "0.75.220",
47
+ "@stacksjs/mobile": "0.75.221",
48
48
  "@stacksjs/sanitizer": "^0.2.534",
49
49
  "@xterm/addon-fit": "^0.11.0",
50
50
  "@xterm/xterm": "^6.0.0",
@@ -12,40 +12,93 @@
12
12
  const mcReplay = useReactiveProp<number>('replay', 0)
13
13
  const mcReveals = derived(() => [mcReplay()])
14
14
  const mcCelebrate = useReactiveProp<boolean>('celebrate', true)
15
+ const mcSurface = useRef('membershipSurface')
16
+ const mcCanHover = useMediaQuery('(hover: hover) and (pointer: fine)')
17
+ const mcReduceMotion = usePreferredReducedMotion()
18
+ let mcStopHover: (() => void) | undefined
19
+
20
+ onMount(() => {
21
+ const surface = mcSurface.current as HTMLElement | null
22
+ if (!surface) return
23
+
24
+ // Measure the stationary hit area, never the rotating card, to avoid feedback jitter.
25
+ const reset = () => {
26
+ surface.style.setProperty('--mc-rotate-x', '0deg')
27
+ surface.style.setProperty('--mc-rotate-y', '0deg')
28
+ surface.style.setProperty('--mc-light-x', '50%')
29
+ surface.style.setProperty('--mc-light-y', '50%')
30
+ surface.style.setProperty('--mc-hover', '0')
31
+ }
32
+ mcStopHover = effect(() => {
33
+ reset()
34
+ if (!mcCanHover() || mcReduceMotion()) return
35
+ const mouse = useMouse({ target: surface, touch: false, resetOnLeave: true })
36
+ const unsubscribe = mouse.subscribe(({ clientX, clientY, isInside }) => {
37
+ if (!isInside) return reset()
38
+ const bounds = surface.getBoundingClientRect()
39
+ if (!bounds.width || !bounds.height) return reset()
40
+ const x = Math.max(0, Math.min(1, (clientX - bounds.left) / bounds.width))
41
+ const y = Math.max(0, Math.min(1, (clientY - bounds.top) / bounds.height))
42
+ surface.style.setProperty('--mc-rotate-x', `${(0.5 - y) * 12}deg`)
43
+ surface.style.setProperty('--mc-rotate-y', `${(x - 0.5) * 16}deg`)
44
+ surface.style.setProperty('--mc-light-x', `${x * 100}%`)
45
+ surface.style.setProperty('--mc-light-y', `${y * 100}%`)
46
+ surface.style.setProperty('--mc-hover', '1')
47
+ })
48
+ return () => {
49
+ unsubscribe()
50
+ mouse.stop()
51
+ reset()
52
+ }
53
+ })
54
+ })
55
+ onDestroy(() => mcStopHover?.())
56
+
15
57
  const mcPieces = [...Array(32).keys()].map(id => ({
16
58
  id,
17
59
  style: `--mc-x:${(id * 37 + 11) % 100}%;--mc-drift:${(id * 29 % 160) - 80}px;--mc-delay:${id % 8 * 65}ms;--mc-turn:${180 + id * 47}deg;--mc-color:var(--membership-card-confetti-${id % 4 + 1},${['#99f6e4', '#e2e8f0', '#5eead4', '#94a3b8'][id % 4]})`,
18
60
  }))
19
61
  </script>
20
62
 
21
- <div :for="reveal in mcReveals" :key="reveal" class="relative mx-auto w-full mc-stage" :class="mcCelebrate ? 'mc-celebrate' : ''" data-membership-reveal>
22
- <div :if="mcCelebrate" class="absolute inset-0 overflow-hidden pointer-events-none mc-confetti" aria-hidden="true">
23
- <span :for="piece in mcPieces" :key="piece.id" class="mc-piece" :style="piece.style"></span>
24
- </div>
25
- <article class="overflow-hidden relative mx-auto w-full mc-metal" :aria-label="mcLabel" data-membership-card>
26
- <div class="absolute inset-0 pointer-events-none mc-grain" aria-hidden="true"></div>
27
- <div class="absolute inset-0 pointer-events-none mc-shine" aria-hidden="true"></div>
28
- <div class="flex relative gap-4 items-start justify-between">
29
- <img :if="mcLogo" class="mc-logo" :src="mcLogo" :alt="mcBrand" width="96" height="38" />
30
- <span :if="!mcLogo" class="font-bold mc-wordmark" :text="mcBrand"></span>
31
- </div>
32
- <p class="relative mt-3 text-xs mc-label" :text="mcLabel"></p>
33
- <div class="relative mc-holder">
34
- <div class="mc-person">
35
- <p class="mb-2 text-xs mc-label" :text="mcNameLabel"></p>
36
- <p class="mc-engraving" :style="{ fontFamily: mcNameFont }" :text="mcName" data-membership-name></p>
63
+ <div class="relative mx-auto w-full mc-stage" data-membership-reveal>
64
+ <div ref="membershipSurface" class="mc-surface">
65
+ <div :for="reveal in mcReveals" :key="reveal" :class="mcCelebrate ? 'mc-celebrate' : ''">
66
+ <div :if="mcCelebrate" class="absolute inset-0 overflow-hidden pointer-events-none mc-confetti" aria-hidden="true">
67
+ <span :for="piece in mcPieces" :key="piece.id" class="mc-piece" :style="piece.style"></span>
37
68
  </div>
38
- <div :if="mcMemberId" class="mc-identity">
39
- <p class="text-xs mc-label" :text="mcMemberIdLabel"></p>
40
- <p class="font-semibold mc-serial" :text="mcMemberId" data-membership-id></p>
69
+ <div class="mc-tilt">
70
+ <article class="overflow-hidden relative mx-auto w-full mc-metal" :aria-label="mcLabel" data-membership-card>
71
+ <div class="absolute inset-0 pointer-events-none mc-grain" aria-hidden="true"></div>
72
+ <div class="absolute inset-0 pointer-events-none mc-reflection" aria-hidden="true"></div>
73
+ <div class="absolute inset-0 pointer-events-none mc-shine" aria-hidden="true"></div>
74
+ <div class="flex relative gap-4 items-start justify-between">
75
+ <img :if="mcLogo" class="mc-logo" :src="mcLogo" :alt="mcBrand" width="96" height="38" />
76
+ <span :if="!mcLogo" class="font-bold mc-wordmark" :text="mcBrand"></span>
77
+ </div>
78
+ <p class="relative mt-3 text-xs mc-label" :text="mcLabel"></p>
79
+ <div class="relative mc-holder">
80
+ <div class="mc-person">
81
+ <p class="mb-2 text-xs mc-label" :text="mcNameLabel"></p>
82
+ <p class="mc-engraving" :style="{ fontFamily: mcNameFont }" :text="mcName" data-membership-name></p>
83
+ </div>
84
+ <div :if="mcMemberId" class="mc-identity">
85
+ <p class="text-xs mc-label" :text="mcMemberIdLabel"></p>
86
+ <p class="font-semibold mc-serial" :text="mcMemberId" data-membership-id></p>
87
+ </div>
88
+ </div>
89
+ <p :if="mcDetail" class="relative mt-5 text-xs mc-detail" :text="mcDetail"></p>
90
+ </article>
41
91
  </div>
42
92
  </div>
43
- <p :if="mcDetail" class="relative mt-5 text-xs mc-detail" :text="mcDetail"></p>
44
- </article>
93
+ </div>
45
94
  </div>
46
95
 
47
96
  <style>
48
97
  .mc-stage { max-width: 28rem; padding: 2rem 0 2.5rem; perspective: 1000px; }
98
+ .mc-surface { isolation: isolate; }
99
+ .mc-tilt { transform: perspective(1000px) rotateX(var(--mc-rotate-x, 0deg)) rotateY(var(--mc-rotate-y, 0deg)) translateY(calc(var(--mc-hover, 0) * -3px)); transition: transform 450ms cubic-bezier(0.2, 0.75, 0.25, 1); }
100
+ .mc-surface:hover .mc-tilt { transition-duration: 160ms; }
101
+ .mc-reflection { opacity: calc(var(--mc-hover, 0) * 0.65); background: radial-gradient(ellipse at var(--mc-light-x, 50%) var(--mc-light-y, 50%), #ffffff38, #ffffff0a 42%, transparent 72%); transition: opacity 350ms ease; }
49
102
  .mc-metal {
50
103
  box-sizing: border-box; min-height: 15.5rem; padding: clamp(1.25rem, 5vw, 2rem); border-radius: 1.25rem;
51
104
  color: var(--membership-card-color, #e2e8f0); border: 1px solid var(--membership-card-border, #87939d);
@@ -79,10 +132,14 @@
79
132
  .mc-celebrate .mc-metal { animation: mc-arrive 1100ms cubic-bezier(0.16, 1, 0.3, 1) both; }
80
133
  .mc-celebrate .mc-shine { animation: mc-polish 1700ms ease-in-out 650ms both; }
81
134
  .mc-celebrate .mc-piece { animation: mc-fall 2400ms cubic-bezier(0.2, 0.65, 0.45, 1) var(--mc-delay) both; }
82
- .mc-metal:hover .mc-shine { transform: translateX(150%) skewX(-20deg); transition: transform 1400ms ease; }
135
+ }
136
+ @media (hover: none), (pointer: coarse) {
137
+ .mc-tilt { transform: none; transition: none; }
138
+ .mc-reflection { display: none; }
83
139
  }
84
140
  @media (prefers-reduced-motion: reduce) {
85
- .mc-confetti, .mc-shine { display: none; }
141
+ .mc-confetti, .mc-shine, .mc-reflection { display: none; }
142
+ .mc-tilt { transform: none; transition: none; }
86
143
  }
87
144
  @keyframes mc-arrive { from { opacity: 0; transform: translateY(32px) rotateX(16deg) rotateY(-12deg) scale(0.92); } to { opacity: 1; transform: none; } }
88
145
  @keyframes mc-polish { from { transform: translateX(-150%) skewX(-20deg); } to { transform: translateX(150%) skewX(-20deg); } }