@getvitops/core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/README.md +29 -0
  2. package/css/animation.css +526 -0
  3. package/css/global.css +17 -0
  4. package/css/index.css +58 -0
  5. package/css/layout.css +723 -0
  6. package/css/patterns/anchor-link.css +66 -0
  7. package/css/patterns/banner.css +64 -0
  8. package/css/patterns/carousel.css +269 -0
  9. package/css/patterns/cluster.css +64 -0
  10. package/css/patterns/code.css +17 -0
  11. package/css/patterns/combobox.css +97 -0
  12. package/css/patterns/comment.css +88 -0
  13. package/css/patterns/copy.css +82 -0
  14. package/css/patterns/details.css +87 -0
  15. package/css/patterns/dialog.css +99 -0
  16. package/css/patterns/drawer.css +108 -0
  17. package/css/patterns/dropdown.css +45 -0
  18. package/css/patterns/forms.css +335 -0
  19. package/css/patterns/grouped.css +86 -0
  20. package/css/patterns/horizontal-scroll.css +40 -0
  21. package/css/patterns/icon.css +72 -0
  22. package/css/patterns/lightbox.css +156 -0
  23. package/css/patterns/list.css +272 -0
  24. package/css/patterns/marquee.css +68 -0
  25. package/css/patterns/masonry.css +40 -0
  26. package/css/patterns/media.css +70 -0
  27. package/css/patterns/nav.css +241 -0
  28. package/css/patterns/notification.css +114 -0
  29. package/css/patterns/overlay.css +28 -0
  30. package/css/patterns/popover.css +68 -0
  31. package/css/patterns/pull-quote.css +71 -0
  32. package/css/patterns/scroll-based.css +227 -0
  33. package/css/patterns/scroll-target.css +124 -0
  34. package/css/patterns/separator.css +130 -0
  35. package/css/patterns/sitenav.css +582 -0
  36. package/css/patterns/split-link.css +113 -0
  37. package/css/patterns/splitter.css +212 -0
  38. package/css/patterns/stack.css +67 -0
  39. package/css/patterns/sticky.css +127 -0
  40. package/css/patterns/subgrid.css +178 -0
  41. package/css/patterns/svg.css +166 -0
  42. package/css/patterns/table.css +106 -0
  43. package/css/patterns/tag.css +75 -0
  44. package/css/patterns/text-effects.css +317 -0
  45. package/css/patterns/tooltip.css +68 -0
  46. package/css/patterns/tree.css +126 -0
  47. package/css/utilities.css +351 -0
  48. package/dist/deferred.js +1 -0
  49. package/dist/elements.js +887 -0
  50. package/dist/polyfills/adoptedStyleSheets.js +1 -0
  51. package/dist/polyfills/css-anchor-positioning-fn.js +17 -0
  52. package/dist/polyfills/global.esm.js +1 -0
  53. package/dist/polyfills/popover.js +63 -0
  54. package/dist/polyfills/template-shadowroot.js +24 -0
  55. package/dist/polyfills/webcomponents-bundle.js +27 -0
  56. package/dist/polyfills.js +1 -0
  57. package/package.json +33 -0
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Tooltip — pattern partial migrated from old-css-lib.
3
+ * Consumes the generated token cascade (src/css/generated/tokens.css).
4
+ */
5
+
6
+ /* ── Tooltip — anchored popover shown on hover/focus ───────────────────────── */
7
+ /* Shown in the top layer via the Popover API: deferred.ts opens it on
8
+ hover/focus, and the trigger's `popovertarget` is the no-JS click fallback.
9
+ The top layer is what makes the flip work — it escapes the page's
10
+ container-query containment (`body { container-type }`), so the fixed
11
+ tooltip's containing block is the viewport and the flip fallbacks resolve
12
+ against the viewport edges (a plain :hover reveal stays trapped in that
13
+ containment and can only shift, never flip). Trigger and tooltip are siblings
14
+ so the tooltip is not a descendant of its own anchor. Several tooltips on one
15
+ page each need a distinct --tooltip anchor name (or an `anchor-scope`
16
+ wrapper); the single shared name here is fine for one-off use. */
17
+ .tooltip-trigger {
18
+ anchor-name: --tooltip-anchor;
19
+ }
20
+
21
+ [popover].tooltip {
22
+ --_p: var(--p-tooltip, var(--p-tooltip-group, var(--p-default)));
23
+ --_br: var(--br-tooltip, var(--br-tooltip-group, var(--br-default)));
24
+ --_ds: var(--ds-tooltip, var(--ds-tooltip-group, var(--ds-default)));
25
+ --_fs: var(--fs-tooltip, var(--fs-tooltip-group, var(--fs-default)));
26
+
27
+ /* Anchored via inset(), NOT position-area: the flip try-tactics only flip
28
+ anchor()-based insets — position-area silently shifts-to-fit. Placement is a
29
+ logical inset + matching self-alignment; overriding them re-points it to any
30
+ side/corner and the flip chain adapts — nothing assumes top/bottom, so the
31
+ same pattern serves an edge icon or an `inline-end` megamenu. `margin` is the
32
+ uniform anchor gap and flips with the inset. (flip-* is Anchor Positioning v2
33
+ — native Chrome only; polyfilled engines keep the default side.) */
34
+ position: fixed;
35
+ position-anchor: --tooltip-anchor;
36
+ inset: auto;
37
+ inset-block-start: anchor(block-end);
38
+ justify-self: anchor-center;
39
+ position-try-fallbacks:
40
+ flip-block,
41
+ flip-inline,
42
+ flip-block flip-inline;
43
+ margin: 0.5rem;
44
+ padding: var(--_p);
45
+ border-radius: var(--_br);
46
+ box-shadow: var(--_ds);
47
+ background: var(--color-surface-xxd);
48
+ color: var(--color-surface-xxl);
49
+ font-size: var(--_fs);
50
+ white-space: nowrap;
51
+ max-inline-size: 20rem;
52
+ pointer-events: none;
53
+
54
+ /* The Popover API toggles display; fade across the top-layer transition. */
55
+ opacity: 0;
56
+ transition:
57
+ opacity 0.15s ease,
58
+ overlay 0.15s allow-discrete,
59
+ display 0.15s allow-discrete;
60
+
61
+ &:popover-open {
62
+ opacity: 1;
63
+
64
+ @starting-style {
65
+ opacity: 0;
66
+ }
67
+ }
68
+ }
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Tree — pattern partial migrated from old-css-lib.
3
+ * Consumes the generated token cascade (src/css/generated/tokens.css).
4
+ */
5
+
6
+ /* ── Tree — hierarchical view over nested lists / <details> ───────────────── */
7
+ .tree {
8
+ --_p: var(--p-tree, var(--p-tree-group, var(--p-default)));
9
+
10
+ list-style: none;
11
+ margin: 0;
12
+ padding: var(--_p);
13
+
14
+ .tree__item {
15
+ position: relative;
16
+ }
17
+
18
+ .tree__item > .tree {
19
+ margin-inline-start: var(--tree-indent, 1.5rem);
20
+ padding-inline-start: var(--tree-indent, 1.5rem);
21
+ border-inline-start: 1px solid var(--color-surface-l);
22
+ }
23
+
24
+ .tree__content,
25
+ details.tree__item > summary {
26
+ display: flex;
27
+ align-items: center;
28
+ gap: var(--tree-gap, 0.25rem);
29
+ padding: 0.25rem 0;
30
+ }
31
+
32
+ .tree__content {
33
+ cursor: default;
34
+ }
35
+
36
+ details.tree__item > summary {
37
+ cursor: pointer;
38
+ list-style: none;
39
+
40
+ &::-webkit-details-marker {
41
+ display: none;
42
+ }
43
+ &::marker {
44
+ content: none;
45
+ }
46
+ &:focus-visible {
47
+ outline: 2px solid var(--tree-focus-color, currentColor);
48
+ outline-offset: 2px;
49
+ }
50
+ }
51
+
52
+ .tree__toggle {
53
+ flex-shrink: 0;
54
+ inline-size: var(--tree-icon-size, 1.25rem);
55
+ block-size: var(--tree-icon-size, 1.25rem);
56
+ display: flex;
57
+ align-items: center;
58
+ justify-content: center;
59
+ transition: transform 0.2s ease;
60
+ }
61
+
62
+ details.tree__item[open] > summary .tree__toggle {
63
+ transform: rotate(90deg);
64
+ }
65
+
66
+ .tree__toggle::before {
67
+ content: '';
68
+ inline-size: 0.5rem;
69
+ block-size: 0.5rem;
70
+ border-inline-end: 2px solid currentColor;
71
+ border-block-end: 2px solid currentColor;
72
+ transform: rotate(-45deg);
73
+ }
74
+
75
+ .tree__icon {
76
+ flex-shrink: 0;
77
+ inline-size: var(--tree-icon-size, 1.25rem);
78
+ block-size: var(--tree-icon-size, 1.25rem);
79
+ display: flex;
80
+ align-items: center;
81
+ justify-content: center;
82
+ }
83
+
84
+ .tree__label {
85
+ flex: 1;
86
+ min-inline-size: 0;
87
+ overflow: hidden;
88
+ text-overflow: ellipsis;
89
+ white-space: nowrap;
90
+ }
91
+
92
+ .tree__actions {
93
+ display: flex;
94
+ gap: 0.25rem;
95
+ opacity: 0;
96
+ transition: opacity 0.15s ease;
97
+ }
98
+
99
+ .tree__item:hover .tree__actions,
100
+ .tree__item:focus-within .tree__actions {
101
+ opacity: 1;
102
+ }
103
+
104
+ .tree__item.tree__item--dragging {
105
+ opacity: 0.5;
106
+ }
107
+
108
+ &.tree--lines .tree__item {
109
+ position: relative;
110
+
111
+ &::before {
112
+ content: '';
113
+ position: absolute;
114
+ inset-inline-start: calc(-1 * var(--tree-indent, 1.5rem) + 0.5rem);
115
+ inset-block-start: 0;
116
+ block-size: 1rem;
117
+ inline-size: calc(var(--tree-indent, 1.5rem) - 0.5rem);
118
+ border-inline-start: 1px solid var(--color-surface-l);
119
+ border-block-end: 1px solid var(--color-surface-l);
120
+ }
121
+ }
122
+
123
+ &.tree--lines > .tree__item::before {
124
+ display: none;
125
+ }
126
+ }
@@ -0,0 +1,351 @@
1
+ /* ═══════════════════════════════════════════════════════════════════════════
2
+ UTILITIES — display / visibility / disclosure (CSS + Bricks output only)
3
+ Tailwind ships hidden/sr-only/block/flex/grid natively, so these live ONLY in
4
+ the static framework and are deliberately NOT emitted by emitTailwind().
5
+
6
+ Responsive variant naming matches layout.css (Tailwind-aligned): the base
7
+ utility is emitted bare, then each tier repeats it with an sm-/md-/lg-/xl-
8
+ prefix inside an unnamed `@container (min-width: Xrem)` block, resolving
9
+ against the nearest container-type ancestor (body { container-type }).
10
+ Breakpoints: sm 30rem · md 48rem · lg 64rem · xl 80rem.
11
+
12
+ CASCADE NOTE: this file MUST be imported AFTER layout.css. Tailwind's
13
+ `hidden md-flex` idiom relies on every breakpoint display variant sitting
14
+ later in the cascade than every bare display utility. layout.css already owns
15
+ bare `.flex` + `.{bp}-flex`; to keep the reveal idiom working we re-emit the
16
+ `.{bp}-flex` reveal variants (identical decls) so they land after this file's
17
+ bare `.hidden`. The later copy wins; behaviour is unchanged.
18
+ ═══════════════════════════════════════════════════════════════════════════ */
19
+
20
+ /* ── Display / visibility — Tailwind-exact base values ──
21
+ Base = mobile. `hidden` hides; the sm-/md-/lg-/xl- variants below REVEAL
22
+ (block/flex/inline/inline-block/grid) or HIDE (`.{bp}-hidden`) at a tier.
23
+ Bare `.flex` is intentionally omitted — layout.css owns it. */
24
+ .block {
25
+ display: block;
26
+ }
27
+ .inline {
28
+ display: inline;
29
+ }
30
+ .inline-block {
31
+ display: inline-block;
32
+ }
33
+ .grid {
34
+ display: grid;
35
+ }
36
+ .hidden {
37
+ display: none;
38
+ }
39
+
40
+ @container (min-width: 30rem) {
41
+ .sm-block {
42
+ display: block;
43
+ }
44
+ .sm-flex {
45
+ display: flex;
46
+ }
47
+ .sm-inline {
48
+ display: inline;
49
+ }
50
+ .sm-inline-block {
51
+ display: inline-block;
52
+ }
53
+ .sm-grid {
54
+ display: grid;
55
+ }
56
+ .sm-hidden {
57
+ display: none;
58
+ }
59
+ }
60
+ @container (min-width: 48rem) {
61
+ .md-block {
62
+ display: block;
63
+ }
64
+ .md-flex {
65
+ display: flex;
66
+ }
67
+ .md-inline {
68
+ display: inline;
69
+ }
70
+ .md-inline-block {
71
+ display: inline-block;
72
+ }
73
+ .md-grid {
74
+ display: grid;
75
+ }
76
+ .md-hidden {
77
+ display: none;
78
+ }
79
+ }
80
+ @container (min-width: 64rem) {
81
+ .lg-block {
82
+ display: block;
83
+ }
84
+ .lg-flex {
85
+ display: flex;
86
+ }
87
+ .lg-inline {
88
+ display: inline;
89
+ }
90
+ .lg-inline-block {
91
+ display: inline-block;
92
+ }
93
+ .lg-grid {
94
+ display: grid;
95
+ }
96
+ .lg-hidden {
97
+ display: none;
98
+ }
99
+ }
100
+ @container (min-width: 80rem) {
101
+ .xl-block {
102
+ display: block;
103
+ }
104
+ .xl-flex {
105
+ display: flex;
106
+ }
107
+ .xl-inline {
108
+ display: inline;
109
+ }
110
+ .xl-inline-block {
111
+ display: inline-block;
112
+ }
113
+ .xl-grid {
114
+ display: grid;
115
+ }
116
+ .xl-hidden {
117
+ display: none;
118
+ }
119
+ }
120
+
121
+ /* ── Screen-reader-only (visually hidden but exposed to AT) ──
122
+ Standard recipe: pull out of flow, clamp to 1px, clip, unwrap. `.not-sr-only`
123
+ reverses it (e.g. reveal a skip-link on focus). Both get sm-/md-/lg-/xl-
124
+ variants so visibility can flip per container tier. */
125
+ .sr-only {
126
+ position: absolute;
127
+ width: 1px;
128
+ height: 1px;
129
+ padding: 0;
130
+ margin: -1px;
131
+ overflow: hidden;
132
+ clip: rect(0, 0, 0, 0); /* legacy fallback */
133
+ clip-path: inset(50%);
134
+ white-space: nowrap;
135
+ border-width: 0;
136
+ }
137
+ .not-sr-only {
138
+ position: static;
139
+ width: auto;
140
+ height: auto;
141
+ padding: 0;
142
+ margin: 0;
143
+ overflow: visible;
144
+ clip: auto;
145
+ clip-path: none;
146
+ white-space: normal;
147
+ }
148
+
149
+ @container (min-width: 30rem) {
150
+ .sm-sr-only {
151
+ position: absolute;
152
+ width: 1px;
153
+ height: 1px;
154
+ padding: 0;
155
+ margin: -1px;
156
+ overflow: hidden;
157
+ clip: rect(0, 0, 0, 0);
158
+ clip-path: inset(50%);
159
+ white-space: nowrap;
160
+ border-width: 0;
161
+ }
162
+ .sm-not-sr-only {
163
+ position: static;
164
+ width: auto;
165
+ height: auto;
166
+ padding: 0;
167
+ margin: 0;
168
+ overflow: visible;
169
+ clip: auto;
170
+ clip-path: none;
171
+ white-space: normal;
172
+ }
173
+ }
174
+ @container (min-width: 48rem) {
175
+ .md-sr-only {
176
+ position: absolute;
177
+ width: 1px;
178
+ height: 1px;
179
+ padding: 0;
180
+ margin: -1px;
181
+ overflow: hidden;
182
+ clip: rect(0, 0, 0, 0);
183
+ clip-path: inset(50%);
184
+ white-space: nowrap;
185
+ border-width: 0;
186
+ }
187
+ .md-not-sr-only {
188
+ position: static;
189
+ width: auto;
190
+ height: auto;
191
+ padding: 0;
192
+ margin: 0;
193
+ overflow: visible;
194
+ clip: auto;
195
+ clip-path: none;
196
+ white-space: normal;
197
+ }
198
+ }
199
+ @container (min-width: 64rem) {
200
+ .lg-sr-only {
201
+ position: absolute;
202
+ width: 1px;
203
+ height: 1px;
204
+ padding: 0;
205
+ margin: -1px;
206
+ overflow: hidden;
207
+ clip: rect(0, 0, 0, 0);
208
+ clip-path: inset(50%);
209
+ white-space: nowrap;
210
+ border-width: 0;
211
+ }
212
+ .lg-not-sr-only {
213
+ position: static;
214
+ width: auto;
215
+ height: auto;
216
+ padding: 0;
217
+ margin: 0;
218
+ overflow: visible;
219
+ clip: auto;
220
+ clip-path: none;
221
+ white-space: normal;
222
+ }
223
+ }
224
+ @container (min-width: 80rem) {
225
+ .xl-sr-only {
226
+ position: absolute;
227
+ width: 1px;
228
+ height: 1px;
229
+ padding: 0;
230
+ margin: -1px;
231
+ overflow: hidden;
232
+ clip: rect(0, 0, 0, 0);
233
+ clip-path: inset(50%);
234
+ white-space: nowrap;
235
+ border-width: 0;
236
+ }
237
+ .xl-not-sr-only {
238
+ position: static;
239
+ width: auto;
240
+ height: auto;
241
+ padding: 0;
242
+ margin: 0;
243
+ overflow: visible;
244
+ clip: auto;
245
+ clip-path: none;
246
+ white-space: normal;
247
+ }
248
+ }
249
+
250
+ /* ═══════════════════════════════════════════════════════════════════════════
251
+ DISCLOSURE — animatable show/hide (auto ↔ 0), layered by support
252
+ Layer 1 (primary, broadly supported): CSS grid 0fr↔1fr hack. Needs ONE child
253
+ wrapper; the wrapper clips its own content as the track reveals.
254
+ Layer 2 (progressive): interpolate-size + native height:auto animation.
255
+ Layer 3 (native <details>): animate ::details-content directly.
256
+ `.reveal-fade` covers the display:none fade case with the allow-discrete +
257
+ @starting-style idiom (same as nav.css `.drawer-menu`).
258
+ Toggle: consumer sets `.is-open` / `[data-open]` (mirrors .is-active /
259
+ [data-active] in animation.css), OR nests under an [open] element (<details>).
260
+ ═══════════════════════════════════════════════════════════════════════════ */
261
+ :root {
262
+ --reveal-duration: 0.4s;
263
+ }
264
+
265
+ /* ── Layer 1: grid-rows hack (primary) ──
266
+ Markup:
267
+ <div class="reveal" id="panel"> <!-- the animated track -->
268
+ <div> … </div> <!-- required single wrapper -->
269
+ </div>
270
+ Toggle .is-open / [data-open] on `.reveal` (JS/Lit), or nest under an [open]
271
+ element (e.g. <details>). The wrapper needs min-height:0 + overflow:hidden so
272
+ the content can be clipped to the 0fr track. */
273
+ .reveal {
274
+ display: grid;
275
+ grid-template-rows: 0fr;
276
+ transition: grid-template-rows var(--reveal-duration) var(--interact-easing, ease);
277
+ }
278
+ .reveal > * {
279
+ min-height: 0;
280
+ overflow: hidden;
281
+ }
282
+ .reveal.is-open,
283
+ .reveal[data-open],
284
+ :where([open]) > .reveal {
285
+ grid-template-rows: 1fr;
286
+ }
287
+
288
+ /* ── Layer 2: native height:auto animation (progressive enhancement) ──
289
+ Where interpolate-size is supported, animate height directly (no wrapper
290
+ needed). Guarded so unsupported engines keep the grid hack above. */
291
+ @supports (interpolate-size: allow-keywords) {
292
+ :root {
293
+ interpolate-size: allow-keywords;
294
+ }
295
+ .reveal-h {
296
+ height: auto;
297
+ overflow: hidden;
298
+ transition: height var(--reveal-duration) var(--interact-easing, ease);
299
+ }
300
+ .reveal-h:not(.is-open):not([data-open]) {
301
+ height: 0;
302
+ }
303
+ }
304
+
305
+ /* ── Layer 3: native <details> disclosure ──
306
+ Markup:
307
+ <details>
308
+ <summary>Toggle</summary>
309
+ … content …
310
+ </details>
311
+ Animate the UA-generated content box directly; interpolate-size (Layer 2)
312
+ lets block-size reach `auto`. Guarded — engines without ::details-content just
313
+ snap open (fully accessible). */
314
+ @supports selector(::details-content) {
315
+ details::details-content {
316
+ overflow: clip;
317
+ block-size: 0;
318
+ transition:
319
+ block-size var(--reveal-duration) var(--interact-easing, ease),
320
+ content-visibility var(--reveal-duration) allow-discrete;
321
+ }
322
+ details[open]::details-content {
323
+ block-size: auto;
324
+ }
325
+ }
326
+
327
+ /* ── display:none fade/slide — allow-discrete + @starting-style ──
328
+ Same idiom as nav.css `.drawer-menu`. Base is display:none; the open state
329
+ restores display and fades in, and `display`/`overlay` are transitioned with
330
+ allow-discrete so the element animates out before it is removed. `overlay` is
331
+ a no-op unless the element is in the top layer (popover/dialog) — harmless.
332
+ Markup: <div class="reveal-fade" [data-open]?> … </div> (toggle .is-open) */
333
+ .reveal-fade {
334
+ display: none;
335
+ opacity: 0;
336
+ transition:
337
+ opacity var(--reveal-duration) var(--interact-easing, ease),
338
+ overlay var(--reveal-duration) allow-discrete,
339
+ display var(--reveal-duration) allow-discrete;
340
+ }
341
+ .reveal-fade.is-open,
342
+ .reveal-fade[data-open] {
343
+ display: block;
344
+ opacity: 1;
345
+ }
346
+ @starting-style {
347
+ .reveal-fade.is-open,
348
+ .reveal-fade[data-open] {
349
+ opacity: 0;
350
+ }
351
+ }
@@ -0,0 +1 @@
1
+ function e(e){let t=[...e.children];parseFloat(getComputedStyle(e).getPropertyValue(`--stagger-amount`));let n=[],r=e.getBoundingClientRect().top;t.forEach(e=>{let t=Math.round(e.getBoundingClientRect().top-r),i=n.find(e=>Math.abs(e.top-t)<10);i||(i={top:t,items:[]},n.push(i)),i.items.push(e)}),n.forEach(({items:e})=>{e.forEach((e,t)=>{e.style.setProperty(`--_stagger-index`,String(t))})})}let t;function n(){clearTimeout(t),t=setTimeout(()=>{requestAnimationFrame(()=>{document.querySelectorAll(`.stagger`).forEach(e)})},100)}const r=new IntersectionObserver((e,t)=>{e.forEach(e=>{e.isIntersecting&&(e.target.classList.add(`is-active`),t.unobserve(e.target))})});function i(e){let t=e.querySelector(`.horizontal-scroll__track`);if(!t)return;let n=Array.from(t.children).reduce((e,t)=>e+t.offsetWidth,0);t.style.width=`${n}px`}document.addEventListener(`click`,e=>{let t=e.target.closest?.(`a[href^="#"]`);if(!t)return;let n=t.closest(`dialog[open]`);n&&n.close()}),window.addEventListener(`load`,()=>{requestAnimationFrame(()=>{document.querySelectorAll(`.stagger`).forEach(e),window.addEventListener(`resize`,n),document.querySelectorAll(`.horizontal-scroll`).forEach(i),document.querySelectorAll(`.animate-trigger`).forEach(e=>{r.observe(e)});let t=new Date().getFullYear();document.querySelectorAll(`[data-current-year]`).forEach(e=>{e.textContent=t.toString()})})});