@vamos-ui/react 0.2.0 → 0.4.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 (166) hide show
  1. package/dist/blocks/block-image.js +1 -1
  2. package/dist/blocks/block-link.js +1 -1
  3. package/dist/blocks/index.d.ts +2 -2
  4. package/dist/blocks/index.js +2 -2
  5. package/dist/blocks/site/_kit-1.d.ts +1 -0
  6. package/dist/blocks/site/_kit-1.js +3 -1
  7. package/dist/blocks/site/announcement-bar.js +1 -1
  8. package/dist/blocks/site/article-layout.d.ts +1 -0
  9. package/dist/blocks/site/article-layout.js +2 -1
  10. package/dist/blocks/site/blog-list.d.ts +1 -0
  11. package/dist/blocks/site/blog-list.js +3 -2
  12. package/dist/blocks/site/contact-dock.js +3 -1
  13. package/dist/blocks/site/contact-form.js +1 -1
  14. package/dist/blocks/site/cta.d.ts +2 -2
  15. package/dist/blocks/site/cta.js +8 -5
  16. package/dist/blocks/site/faq.js +2 -1
  17. package/dist/blocks/site/feature-grid.d.ts +1 -0
  18. package/dist/blocks/site/feature-grid.js +7 -5
  19. package/dist/blocks/site/footer.d.ts +1 -1
  20. package/dist/blocks/site/footer.js +8 -7
  21. package/dist/blocks/site/gallery-section.d.ts +6 -1
  22. package/dist/blocks/site/gallery-section.js +6 -4
  23. package/dist/blocks/site/hero.d.ts +3 -2
  24. package/dist/blocks/site/hero.js +14 -6
  25. package/dist/blocks/site/logo-strip.d.ts +6 -3
  26. package/dist/blocks/site/logo-strip.js +8 -7
  27. package/dist/blocks/site/map-hours.d.ts +2 -2
  28. package/dist/blocks/site/map-hours.js +4 -2
  29. package/dist/blocks/site/media-text.d.ts +4 -1
  30. package/dist/blocks/site/media-text.js +6 -4
  31. package/dist/blocks/site/menu-list.d.ts +7 -3
  32. package/dist/blocks/site/menu-list.js +34 -7
  33. package/dist/blocks/site/navbar.d.ts +1 -0
  34. package/dist/blocks/site/navbar.js +6 -5
  35. package/dist/blocks/site/not-found.js +2 -1
  36. package/dist/blocks/site/page-intro.d.ts +1 -0
  37. package/dist/blocks/site/page-intro.js +2 -1
  38. package/dist/blocks/site/pricing-table.js +2 -1
  39. package/dist/blocks/site/process.d.ts +1 -0
  40. package/dist/blocks/site/process.js +4 -2
  41. package/dist/blocks/site/registry-1.d.ts +1 -1
  42. package/dist/blocks/site/registry-2.d.ts +5 -0
  43. package/dist/blocks/site/registry-2.js +2 -2
  44. package/dist/blocks/site/rich-text-section.js +2 -1
  45. package/dist/blocks/site/shared/heading-lines.d.ts +9 -0
  46. package/dist/blocks/site/shared/heading-lines.js +32 -0
  47. package/dist/blocks/site/shared/image-sizes.d.ts +25 -0
  48. package/dist/blocks/site/shared/image-sizes.js +37 -0
  49. package/dist/blocks/site/shared/island-keys.d.ts +1 -1
  50. package/dist/blocks/site/shared/island-keys.js +1 -1
  51. package/dist/blocks/site/shared/labels-2.d.ts +9 -1
  52. package/dist/blocks/site/shared/labels-2.js +24 -6
  53. package/dist/blocks/site/shared/open-now.d.ts +1 -1
  54. package/dist/blocks/site/shared/open-now.js +1 -1
  55. package/dist/blocks/site/shared/opening-hours.d.ts +18 -2
  56. package/dist/blocks/site/shared/opening-hours.js +36 -7
  57. package/dist/blocks/site/shared/tap.d.ts +9 -0
  58. package/dist/blocks/site/shared/tap.js +16 -0
  59. package/dist/blocks/site/site-shell.d.ts +11 -0
  60. package/dist/blocks/site/site-shell.js +43 -16
  61. package/dist/blocks/site/stats-band.d.ts +3 -1
  62. package/dist/blocks/site/stats-band.js +11 -7
  63. package/dist/blocks/site/team.d.ts +1 -1
  64. package/dist/blocks/site/team.js +4 -3
  65. package/dist/blocks/site/testimonials.d.ts +2 -2
  66. package/dist/blocks/site/testimonials.js +5 -4
  67. package/dist/business/index.d.ts +1 -0
  68. package/dist/business/index.js +2 -0
  69. package/dist/business/signer-status.d.ts +53 -0
  70. package/dist/business/signer-status.js +76 -0
  71. package/dist/charts/bar-chart.js +6 -2
  72. package/dist/charts/chart-shell.d.ts +9 -2
  73. package/dist/charts/chart-shell.js +10 -4
  74. package/dist/charts/chart.js +1 -1
  75. package/dist/charts/combo-chart.js +5 -7
  76. package/dist/charts/utils.d.ts +10 -0
  77. package/dist/charts/utils.js +46 -0
  78. package/dist/components/_qr-core.d.ts +26 -0
  79. package/dist/components/_qr-core.js +376 -0
  80. package/dist/components/activity-timeline.js +5 -5
  81. package/dist/components/aspect-ratio.d.ts +26 -0
  82. package/dist/components/aspect-ratio.js +42 -0
  83. package/dist/components/backup-codes.d.ts +42 -0
  84. package/dist/components/backup-codes.js +67 -0
  85. package/dist/components/breadcrumb.d.ts +2 -2
  86. package/dist/components/breadcrumb.js +1 -1
  87. package/dist/components/carousel.d.ts +12 -3
  88. package/dist/components/carousel.js +8 -5
  89. package/dist/components/collapsible.d.ts +36 -0
  90. package/dist/components/collapsible.js +37 -0
  91. package/dist/components/command.d.ts +8 -2
  92. package/dist/components/command.js +7 -2
  93. package/dist/components/image.d.ts +18 -2
  94. package/dist/components/image.js +12 -5
  95. package/dist/components/input.d.ts +1 -1
  96. package/dist/components/input.js +1 -1
  97. package/dist/components/menubar.d.ts +96 -0
  98. package/dist/components/menubar.js +123 -0
  99. package/dist/components/pin-map.d.ts +58 -0
  100. package/dist/components/pin-map.js +167 -0
  101. package/dist/components/placeholder-art.d.ts +51 -0
  102. package/dist/components/placeholder-art.js +82 -0
  103. package/dist/components/qr-code.d.ts +36 -0
  104. package/dist/components/qr-code.js +27 -0
  105. package/dist/components/record-detail-layout.d.ts +2 -2
  106. package/dist/components/record-detail-layout.js +1 -1
  107. package/dist/components/sidebar.js +8 -8
  108. package/dist/components/sla-timer.d.ts +75 -0
  109. package/dist/components/sla-timer.js +142 -0
  110. package/dist/components/slug-input.js +1 -1
  111. package/dist/components/tour.d.ts +60 -0
  112. package/dist/components/tour.js +139 -0
  113. package/dist/index.d.ts +9 -0
  114. package/dist/index.js +9 -0
  115. package/dist/lib/public.d.ts +1 -0
  116. package/dist/lib/public.js +1 -0
  117. package/dist/lib/value-format.js +1 -1
  118. package/dist/locale-data/core/holidays.d.ts +1 -1
  119. package/dist/locale-data/core/holidays.js +1 -1
  120. package/dist/locales/ar.d.ts +2087 -0
  121. package/dist/locales/ar.js +2088 -0
  122. package/dist/locales/de.d.ts +2087 -0
  123. package/dist/locales/de.js +2088 -0
  124. package/dist/locales/en.d.ts +1 -0
  125. package/dist/locales/en.js +1 -0
  126. package/dist/locales/es.d.ts +2087 -0
  127. package/dist/locales/es.js +2087 -0
  128. package/dist/locales/fr.d.ts +2087 -0
  129. package/dist/locales/fr.js +2088 -0
  130. package/dist/locales/tr.d.ts +1 -0
  131. package/dist/locales/tr.js +1 -0
  132. package/dist/media/gallery.js +3 -1
  133. package/dist/media/media-library.js +1 -1
  134. package/dist/motion/core.d.ts +32 -0
  135. package/dist/motion/core.js +77 -0
  136. package/dist/motion/count-up.d.ts +29 -0
  137. package/dist/motion/count-up.js +92 -0
  138. package/dist/motion/index.d.ts +11 -0
  139. package/dist/motion/index.js +13 -0
  140. package/dist/motion/motion-scope.d.ts +17 -0
  141. package/dist/motion/motion-scope.js +16 -0
  142. package/dist/motion/page-transition.d.ts +33 -0
  143. package/dist/motion/page-transition.js +61 -0
  144. package/dist/motion/parallax.d.ts +37 -0
  145. package/dist/motion/parallax.js +90 -0
  146. package/dist/motion/pointer.d.ts +38 -0
  147. package/dist/motion/pointer.js +117 -0
  148. package/dist/motion/reveal.d.ts +72 -0
  149. package/dist/motion/reveal.js +133 -0
  150. package/dist/motion/scroll-shrink.d.ts +18 -0
  151. package/dist/motion/scroll-shrink.js +47 -0
  152. package/dist/motion/skeleton-swap.d.ts +17 -0
  153. package/dist/motion/skeleton-swap.js +43 -0
  154. package/dist/motion/text-reveal.d.ts +32 -0
  155. package/dist/motion/text-reveal.js +31 -0
  156. package/dist/motion/ticker.d.ts +35 -0
  157. package/dist/motion/ticker.js +16 -0
  158. package/dist/render/block-renderer.js +1 -1
  159. package/dist/sortable/sortable-tree.d.ts +4 -0
  160. package/dist/sortable/sortable-tree.js +16 -4
  161. package/dist/styles/blocks.css +21 -12
  162. package/dist/styles/editors.css +2 -1
  163. package/dist/styles/media.css +31 -5
  164. package/dist/styles/motion.css +389 -0
  165. package/dist/styles.css +41 -10
  166. package/package.json +5 -1
@@ -0,0 +1,376 @@
1
+ // QR Code Model 2 encoder (ISO/IEC 18004), byte mode, versions 1–40, all four error
2
+ // correction levels, automatic mask choice. Pure and dependency-free so it runs in RSC.
3
+ // Follows the structure of the public-domain-style reference algorithm (Nayuki).
4
+ const ECL_INDEX = { L: 0, M: 1, Q: 2, H: 3 };
5
+ const ECL_FORMAT = { L: 1, M: 0, Q: 3, H: 2 };
6
+ // prettier-ignore
7
+ const ECC_CODEWORDS_PER_BLOCK = [
8
+ [-1, 7, 10, 15, 20, 26, 18, 20, 24, 30, 18, 20, 24, 26, 30, 22, 24, 28, 30, 28, 28, 28, 28, 30, 30, 26, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30],
9
+ [-1, 10, 16, 26, 18, 24, 16, 18, 22, 22, 26, 30, 22, 22, 24, 24, 28, 28, 26, 26, 26, 26, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28],
10
+ [-1, 13, 22, 18, 26, 18, 24, 18, 22, 20, 24, 28, 26, 24, 20, 30, 24, 28, 28, 26, 30, 28, 30, 30, 30, 30, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30],
11
+ [-1, 17, 28, 22, 16, 22, 28, 26, 26, 24, 28, 24, 28, 22, 24, 24, 30, 28, 28, 26, 28, 30, 24, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30],
12
+ ];
13
+ // prettier-ignore
14
+ const NUM_ERROR_CORRECTION_BLOCKS = [
15
+ [-1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 6, 7, 8, 8, 9, 9, 10, 12, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 24, 25],
16
+ [-1, 1, 1, 1, 2, 2, 4, 4, 4, 5, 5, 5, 8, 9, 9, 10, 10, 11, 13, 14, 16, 17, 17, 18, 20, 21, 23, 25, 26, 28, 29, 31, 33, 35, 37, 38, 40, 43, 45, 47, 49],
17
+ [-1, 1, 1, 2, 2, 4, 4, 6, 6, 8, 8, 8, 10, 12, 16, 12, 17, 16, 18, 21, 20, 23, 23, 25, 27, 29, 34, 34, 35, 38, 40, 43, 45, 48, 51, 53, 56, 59, 62, 65, 68],
18
+ [-1, 1, 1, 2, 4, 4, 4, 5, 6, 8, 8, 11, 11, 16, 16, 18, 16, 19, 21, 25, 25, 25, 34, 30, 32, 35, 37, 40, 42, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81],
19
+ ];
20
+ const bit = (x, i) => ((x >>> i) & 1) !== 0;
21
+ function rawDataModules(ver) {
22
+ let result = (16 * ver + 128) * ver + 64;
23
+ if (ver >= 2) {
24
+ const numAlign = Math.floor(ver / 7) + 2;
25
+ result -= (25 * numAlign - 10) * numAlign - 55;
26
+ if (ver >= 7)
27
+ result -= 36;
28
+ }
29
+ return result;
30
+ }
31
+ function dataCodewords(ver, ecl) {
32
+ const e = ECL_INDEX[ecl];
33
+ return Math.floor(rawDataModules(ver) / 8) - ECC_CODEWORDS_PER_BLOCK[e][ver] * NUM_ERROR_CORRECTION_BLOCKS[e][ver];
34
+ }
35
+ /* Reed–Solomon over GF(2^8), polynomial 0x11D. */
36
+ function gfMul(x, y) {
37
+ let z = 0;
38
+ for (let i = 7; i >= 0; i--) {
39
+ z = (z << 1) ^ ((z >>> 7) * 0x11d);
40
+ z ^= ((y >>> i) & 1) * x;
41
+ }
42
+ return z & 0xff;
43
+ }
44
+ function rsDivisor(degree) {
45
+ const result = new Array(degree - 1).fill(0);
46
+ result.push(1);
47
+ let root = 1;
48
+ for (let i = 0; i < degree; i++) {
49
+ for (let j = 0; j < result.length; j++) {
50
+ result[j] = gfMul(result[j], root);
51
+ if (j + 1 < result.length)
52
+ result[j] ^= result[j + 1];
53
+ }
54
+ root = gfMul(root, 0x02);
55
+ }
56
+ return result;
57
+ }
58
+ function rsRemainder(data, divisor) {
59
+ const result = divisor.map(() => 0);
60
+ for (const b of data) {
61
+ const factor = b ^ result.shift();
62
+ result.push(0);
63
+ divisor.forEach((coef, i) => (result[i] ^= gfMul(coef, factor)));
64
+ }
65
+ return result;
66
+ }
67
+ /** UTF-8 bytes without TextEncoder (works everywhere). */
68
+ function utf8(text) {
69
+ const out = [];
70
+ for (const ch of text) {
71
+ const cp = ch.codePointAt(0);
72
+ if (cp < 0x80)
73
+ out.push(cp);
74
+ else if (cp < 0x800)
75
+ out.push(0xc0 | (cp >> 6), 0x80 | (cp & 63));
76
+ else if (cp < 0x10000)
77
+ out.push(0xe0 | (cp >> 12), 0x80 | ((cp >> 6) & 63), 0x80 | (cp & 63));
78
+ else
79
+ out.push(0xf0 | (cp >> 18), 0x80 | ((cp >> 12) & 63), 0x80 | ((cp >> 6) & 63), 0x80 | (cp & 63));
80
+ }
81
+ return out;
82
+ }
83
+ class Grid {
84
+ version;
85
+ size;
86
+ modules;
87
+ fn;
88
+ constructor(version) {
89
+ this.version = version;
90
+ this.size = version * 4 + 17;
91
+ this.modules = Array.from({ length: this.size }, () => new Array(this.size).fill(false));
92
+ this.fn = Array.from({ length: this.size }, () => new Array(this.size).fill(false));
93
+ }
94
+ setFn(x, y, dark) {
95
+ this.modules[y][x] = dark;
96
+ this.fn[y][x] = true;
97
+ }
98
+ alignmentPositions() {
99
+ if (this.version === 1)
100
+ return [];
101
+ const numAlign = Math.floor(this.version / 7) + 2;
102
+ const step = Math.floor((this.version * 8 + numAlign * 3 + 5) / (numAlign * 4 - 4)) * 2;
103
+ const result = [6];
104
+ for (let pos = this.size - 7; result.length < numAlign; pos -= step)
105
+ result.splice(1, 0, pos);
106
+ return result;
107
+ }
108
+ drawFunctionPatterns(ecl) {
109
+ const n = this.size;
110
+ for (let i = 0; i < n; i++) {
111
+ this.setFn(6, i, i % 2 === 0);
112
+ this.setFn(i, 6, i % 2 === 0);
113
+ }
114
+ this.finder(3, 3);
115
+ this.finder(n - 4, 3);
116
+ this.finder(3, n - 4);
117
+ const pos = this.alignmentPositions();
118
+ const k = pos.length;
119
+ for (let i = 0; i < k; i++)
120
+ for (let j = 0; j < k; j++) {
121
+ if ((i === 0 && j === 0) || (i === 0 && j === k - 1) || (i === k - 1 && j === 0))
122
+ continue;
123
+ for (let dy = -2; dy <= 2; dy++)
124
+ for (let dx = -2; dx <= 2; dx++)
125
+ this.setFn(pos[i] + dx, pos[j] + dy, Math.max(Math.abs(dx), Math.abs(dy)) !== 1);
126
+ }
127
+ this.drawFormat(ecl, 0);
128
+ this.drawVersion();
129
+ }
130
+ finder(x, y) {
131
+ for (let dy = -4; dy <= 4; dy++)
132
+ for (let dx = -4; dx <= 4; dx++) {
133
+ const d = Math.max(Math.abs(dx), Math.abs(dy));
134
+ const xx = x + dx;
135
+ const yy = y + dy;
136
+ if (xx >= 0 && xx < this.size && yy >= 0 && yy < this.size)
137
+ this.setFn(xx, yy, d !== 2 && d !== 4);
138
+ }
139
+ }
140
+ drawFormat(ecl, mask) {
141
+ const data = (ECL_FORMAT[ecl] << 3) | mask;
142
+ let rem = data;
143
+ for (let i = 0; i < 10; i++)
144
+ rem = (rem << 1) ^ ((rem >>> 9) * 0x537);
145
+ const bits = ((data << 10) | rem) ^ 0x5412;
146
+ const n = this.size;
147
+ for (let i = 0; i <= 5; i++)
148
+ this.setFn(8, i, bit(bits, i));
149
+ this.setFn(8, 7, bit(bits, 6));
150
+ this.setFn(8, 8, bit(bits, 7));
151
+ this.setFn(7, 8, bit(bits, 8));
152
+ for (let i = 9; i < 15; i++)
153
+ this.setFn(14 - i, 8, bit(bits, i));
154
+ for (let i = 0; i < 8; i++)
155
+ this.setFn(n - 1 - i, 8, bit(bits, i));
156
+ for (let i = 8; i < 15; i++)
157
+ this.setFn(8, n - 15 + i, bit(bits, i));
158
+ this.setFn(8, n - 8, true);
159
+ }
160
+ drawVersion() {
161
+ if (this.version < 7)
162
+ return;
163
+ let rem = this.version;
164
+ for (let i = 0; i < 12; i++)
165
+ rem = (rem << 1) ^ ((rem >>> 11) * 0x1f25);
166
+ const bits = (this.version << 12) | rem;
167
+ for (let i = 0; i < 18; i++) {
168
+ const b = bit(bits, i);
169
+ const a = this.size - 11 + (i % 3);
170
+ const c = Math.floor(i / 3);
171
+ this.setFn(a, c, b);
172
+ this.setFn(c, a, b);
173
+ }
174
+ }
175
+ drawCodewords(data) {
176
+ let i = 0;
177
+ const n = this.size;
178
+ for (let right = n - 1; right >= 1; right -= 2) {
179
+ if (right === 6)
180
+ right = 5;
181
+ for (let vert = 0; vert < n; vert++)
182
+ for (let j = 0; j < 2; j++) {
183
+ const x = right - j;
184
+ const upward = ((right + 1) & 2) === 0;
185
+ const y = upward ? n - 1 - vert : vert;
186
+ if (!this.fn[y][x] && i < data.length * 8) {
187
+ this.modules[y][x] = bit(data[i >>> 3], 7 - (i & 7));
188
+ i++;
189
+ }
190
+ }
191
+ }
192
+ }
193
+ applyMask(mask) {
194
+ for (let y = 0; y < this.size; y++)
195
+ for (let x = 0; x < this.size; x++) {
196
+ let invert;
197
+ switch (mask) {
198
+ case 0:
199
+ invert = (x + y) % 2 === 0;
200
+ break;
201
+ case 1:
202
+ invert = y % 2 === 0;
203
+ break;
204
+ case 2:
205
+ invert = x % 3 === 0;
206
+ break;
207
+ case 3:
208
+ invert = (x + y) % 3 === 0;
209
+ break;
210
+ case 4:
211
+ invert = (Math.floor(x / 3) + Math.floor(y / 2)) % 2 === 0;
212
+ break;
213
+ case 5:
214
+ invert = ((x * y) % 2) + ((x * y) % 3) === 0;
215
+ break;
216
+ case 6:
217
+ invert = (((x * y) % 2) + ((x * y) % 3)) % 2 === 0;
218
+ break;
219
+ default: invert = (((x + y) % 2) + ((x * y) % 3)) % 2 === 0;
220
+ }
221
+ if (!this.fn[y][x] && invert)
222
+ this.modules[y][x] = !this.modules[y][x];
223
+ }
224
+ }
225
+ penalty() {
226
+ const n = this.size;
227
+ const m = this.modules;
228
+ let score = 0;
229
+ const line = (get) => {
230
+ let run = 1;
231
+ let s = 0;
232
+ for (let i = 1; i <= n; i++) {
233
+ if (i < n && get(i) === get(i - 1))
234
+ run++;
235
+ else {
236
+ if (run >= 5)
237
+ s += 3 + (run - 5);
238
+ run = 1;
239
+ }
240
+ }
241
+ // Finder-like 1:1:3:1:1 with four light modules on one side.
242
+ for (let i = 0; i + 10 < n + 4; i++) {
243
+ const at = (k) => (k < 0 || k >= n ? false : get(k));
244
+ const core = at(i) && !at(i + 1) && at(i + 2) && at(i + 3) && at(i + 4) && !at(i + 5) && at(i + 6);
245
+ if (!core)
246
+ continue;
247
+ const before = !at(i - 1) && !at(i - 2) && !at(i - 3) && !at(i - 4);
248
+ const after = !at(i + 7) && !at(i + 8) && !at(i + 9) && !at(i + 10);
249
+ if (before || after)
250
+ s += 40;
251
+ }
252
+ return s;
253
+ };
254
+ for (let y = 0; y < n; y++)
255
+ score += line((x) => m[y][x]);
256
+ for (let x = 0; x < n; x++)
257
+ score += line((y) => m[y][x]);
258
+ for (let y = 0; y < n - 1; y++)
259
+ for (let x = 0; x < n - 1; x++) {
260
+ const c = m[y][x];
261
+ if (c === m[y][x + 1] && c === m[y + 1][x] && c === m[y + 1][x + 1])
262
+ score += 3;
263
+ }
264
+ let dark = 0;
265
+ for (const row of m)
266
+ for (const c of row)
267
+ if (c)
268
+ dark++;
269
+ const total = n * n;
270
+ score += (Math.ceil(Math.abs(dark * 20 - total * 10) / total) - 1) * 10;
271
+ return score;
272
+ }
273
+ }
274
+ /**
275
+ * Encode text (UTF-8, byte mode) as a QR matrix.
276
+ * Throws when the text does not fit version 40 at the chosen level.
277
+ *
278
+ * ```ts
279
+ * const qr = encodeQr("otpauth://totp/Northpoint:ada@example.com?secret=…", { errorCorrection: "M" });
280
+ * qr.size; // 41 (version 6)
281
+ * ```
282
+ */
283
+ export function encodeQr(text, options = {}) {
284
+ const ecl = options.errorCorrection ?? "M";
285
+ const bytes = utf8(text);
286
+ let version = Math.max(1, Math.min(40, options.minVersion ?? 1));
287
+ let capacityBits = 0;
288
+ for (;; version++) {
289
+ if (version > 40)
290
+ throw new RangeError("QR: text is too long to encode");
291
+ const ccBits = version < 10 ? 8 : 16;
292
+ capacityBits = dataCodewords(version, ecl) * 8;
293
+ if (4 + ccBits + bytes.length * 8 <= capacityBits)
294
+ break;
295
+ }
296
+ // Bit stream: mode (byte = 0100), length, data, terminator, padding.
297
+ const bits = [];
298
+ const push = (value, len) => {
299
+ for (let i = len - 1; i >= 0; i--)
300
+ bits.push((value >>> i) & 1);
301
+ };
302
+ push(0b0100, 4);
303
+ push(bytes.length, version < 10 ? 8 : 16);
304
+ for (const b of bytes)
305
+ push(b, 8);
306
+ push(0, Math.min(4, capacityBits - bits.length));
307
+ push(0, (8 - (bits.length % 8)) % 8);
308
+ for (let pad = 0xec; bits.length < capacityBits; pad ^= 0xec ^ 0x11)
309
+ push(pad, 8);
310
+ const data = [];
311
+ for (let i = 0; i < bits.length; i += 8)
312
+ data.push(bits.slice(i, i + 8).reduce((acc, b) => (acc << 1) | b, 0));
313
+ // Error correction + interleave.
314
+ const e = ECL_INDEX[ecl];
315
+ const numBlocks = NUM_ERROR_CORRECTION_BLOCKS[e][version];
316
+ const eccLen = ECC_CODEWORDS_PER_BLOCK[e][version];
317
+ const rawCodewords = Math.floor(rawDataModules(version) / 8);
318
+ const numShort = numBlocks - (rawCodewords % numBlocks);
319
+ const shortLen = Math.floor(rawCodewords / numBlocks);
320
+ const divisor = rsDivisor(eccLen);
321
+ const blocks = [];
322
+ for (let i = 0, k = 0; i < numBlocks; i++) {
323
+ const dat = data.slice(k, k + shortLen - eccLen + (i < numShort ? 0 : 1));
324
+ k += dat.length;
325
+ const ecc = rsRemainder(dat, divisor);
326
+ if (i < numShort)
327
+ dat.push(0);
328
+ blocks.push(dat.concat(ecc));
329
+ }
330
+ const codewords = [];
331
+ for (let i = 0; i < blocks[0].length; i++)
332
+ blocks.forEach((block, j) => {
333
+ if (i !== shortLen - eccLen || j >= numShort)
334
+ codewords.push(block[i]);
335
+ });
336
+ // Place, then pick the mask with the lowest penalty.
337
+ const grid = new Grid(version);
338
+ grid.drawFunctionPatterns(ecl);
339
+ grid.drawCodewords(codewords);
340
+ let mask = options.mask ?? -1;
341
+ if (mask < 0 || mask > 7) {
342
+ let best = Infinity;
343
+ for (let candidate = 0; candidate < 8; candidate++) {
344
+ grid.applyMask(candidate);
345
+ grid.drawFormat(ecl, candidate);
346
+ const p = grid.penalty();
347
+ if (p < best) {
348
+ best = p;
349
+ mask = candidate;
350
+ }
351
+ grid.applyMask(candidate); // undo (XOR)
352
+ }
353
+ }
354
+ grid.applyMask(mask);
355
+ grid.drawFormat(ecl, mask);
356
+ return { size: grid.size, version, mask, errorCorrection: ecl, modules: grid.modules };
357
+ }
358
+ /** One SVG path (`d`) drawing every dark module, offset by `margin` modules. */
359
+ export function qrPath(qr, margin = 0) {
360
+ let d = "";
361
+ for (let y = 0; y < qr.size; y++) {
362
+ let x = 0;
363
+ while (x < qr.size) {
364
+ if (!qr.modules[y][x]) {
365
+ x++;
366
+ continue;
367
+ }
368
+ let run = 1;
369
+ while (x + run < qr.size && qr.modules[y][x + run])
370
+ run++;
371
+ d += `M${x + margin} ${y + margin}h${run}v1h-${run}z`;
372
+ x += run;
373
+ }
374
+ }
375
+ return d;
376
+ }
@@ -30,11 +30,11 @@ const indicatorVariants = cva("relative z-[1] grid size-(--tl-ind) shrink-0 plac
30
30
  variants: {
31
31
  tone: {
32
32
  neutral: "border-line bg-[color-mix(in_oklch,var(--surface)_90%,var(--scene))]",
33
- accent: "tone-accent border-[color-mix(in_srgb,var(--tone)_35%,var(--line))] bg-[color-mix(in_oklch,var(--tone)_14%,color-mix(in_oklch,var(--surface)_92%,var(--scene)))] text-(--tone)",
34
- success: "tone-success border-[color-mix(in_srgb,var(--tone)_35%,var(--line))] bg-[color-mix(in_oklch,var(--tone)_14%,color-mix(in_oklch,var(--surface)_92%,var(--scene)))] text-(--tone)",
35
- warning: "tone-warning border-[color-mix(in_srgb,var(--tone)_35%,var(--line))] bg-[color-mix(in_oklch,var(--tone)_14%,color-mix(in_oklch,var(--surface)_92%,var(--scene)))] text-(--tone)",
36
- danger: "tone-danger border-[color-mix(in_srgb,var(--tone)_35%,var(--line))] bg-[color-mix(in_oklch,var(--tone)_14%,color-mix(in_oklch,var(--surface)_92%,var(--scene)))] text-(--tone)",
37
- info: "tone-info border-[color-mix(in_srgb,var(--tone)_35%,var(--line))] bg-[color-mix(in_oklch,var(--tone)_14%,color-mix(in_oklch,var(--surface)_92%,var(--scene)))] text-(--tone)",
33
+ accent: "tone-accent border-[color-mix(in_srgb,var(--tone)_35%,var(--line))] bg-[color-mix(in_oklch,var(--tone)_14%,color-mix(in_oklch,var(--surface)_92%,var(--scene)))] text-(--tone-ink)",
34
+ success: "tone-success border-[color-mix(in_srgb,var(--tone)_35%,var(--line))] bg-[color-mix(in_oklch,var(--tone)_14%,color-mix(in_oklch,var(--surface)_92%,var(--scene)))] text-(--tone-ink)",
35
+ warning: "tone-warning border-[color-mix(in_srgb,var(--tone)_35%,var(--line))] bg-[color-mix(in_oklch,var(--tone)_14%,color-mix(in_oklch,var(--surface)_92%,var(--scene)))] text-(--tone-ink)",
36
+ danger: "tone-danger border-[color-mix(in_srgb,var(--tone)_35%,var(--line))] bg-[color-mix(in_oklch,var(--tone)_14%,color-mix(in_oklch,var(--surface)_92%,var(--scene)))] text-(--tone-ink)",
37
+ info: "tone-info border-[color-mix(in_srgb,var(--tone)_35%,var(--line))] bg-[color-mix(in_oklch,var(--tone)_14%,color-mix(in_oklch,var(--surface)_92%,var(--scene)))] text-(--tone-ink)",
38
38
  },
39
39
  },
40
40
  defaultVariants: { tone: "neutral" },
@@ -0,0 +1,26 @@
1
+ import * as React from "react";
2
+ import { type VariantProps } from "class-variance-authority";
3
+ /** `"16/9"`, `"4/3"`, `"1/1"`… or a number (`1.5`). */
4
+ export type AspectRatioValue = `${number}/${number}` | number;
5
+ /** `"16/9"` → 1.777…, `"16:9"` → 1.777…, `1.5` → 1.5. Invalid values return `undefined`. */
6
+ export declare function parseAspectRatio(ratio: AspectRatioValue | string | undefined): number | undefined;
7
+ export declare const aspectRatioVariants: (props?: ({
8
+ rounded?: "ui" | "ui-lg" | "full" | "none" | null | undefined;
9
+ fit?: "fill" | "contain" | "cover" | null | undefined;
10
+ tone?: "inset" | "none" | null | undefined;
11
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
12
+ export interface AspectRatioProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof aspectRatioVariants> {
13
+ /** Width ÷ height. `"16/9"` (default), `"4/3"`, `"1/1"`, `"21/9"` or a number. */
14
+ ratio?: AspectRatioValue;
15
+ }
16
+ /**
17
+ * Keeps a box at a fixed ratio whatever its width, and stretches the direct child to fill it —
18
+ * an iframe, a video, a map, an image or any element. Pure CSS (`aspect-ratio`), server-safe.
19
+ *
20
+ * ```tsx
21
+ * <AspectRatio ratio="16/9" rounded="ui-lg">
22
+ * <iframe src="https://www.youtube-nocookie.com/embed/…" title="Product tour" />
23
+ * </AspectRatio>
24
+ * ```
25
+ */
26
+ export declare const AspectRatio: React.ForwardRefExoticComponent<AspectRatioProps & React.RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,42 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import { cva } from "class-variance-authority";
4
+ import { cn } from "../lib/cn.js";
5
+ /** `"16/9"` → 1.777…, `"16:9"` → 1.777…, `1.5` → 1.5. Invalid values return `undefined`. */
6
+ export function parseAspectRatio(ratio) {
7
+ if (typeof ratio === "number")
8
+ return Number.isFinite(ratio) && ratio > 0 ? ratio : undefined;
9
+ if (!ratio)
10
+ return undefined;
11
+ const [w, h] = ratio.split(/[/:]/).map((s) => Number(s.trim()));
12
+ if (w && h && w > 0 && h > 0)
13
+ return w / h;
14
+ const n = Number(ratio);
15
+ return Number.isFinite(n) && n > 0 ? n : undefined;
16
+ }
17
+ export const aspectRatioVariants = cva("relative isolate block w-full overflow-hidden", {
18
+ variants: {
19
+ rounded: { none: "", ui: "rounded-ui", "ui-lg": "rounded-ui-lg", full: "rounded-full" },
20
+ /** How a direct `img` / `video` child fills the box. */
21
+ fit: { cover: "[&>img]:object-cover [&>video]:object-cover", contain: "[&>img]:object-contain [&>video]:object-contain", fill: "[&>img]:object-fill [&>video]:object-fill" },
22
+ /** `inset`: a `surface-2` backdrop (letterboxing for `contain`, a frame while an iframe loads). */
23
+ tone: { none: "", inset: "bg-surface-2" },
24
+ },
25
+ defaultVariants: { rounded: "none", fit: "cover", tone: "none" },
26
+ });
27
+ /**
28
+ * Keeps a box at a fixed ratio whatever its width, and stretches the direct child to fill it —
29
+ * an iframe, a video, a map, an image or any element. Pure CSS (`aspect-ratio`), server-safe.
30
+ *
31
+ * ```tsx
32
+ * <AspectRatio ratio="16/9" rounded="ui-lg">
33
+ * <iframe src="https://www.youtube-nocookie.com/embed/…" title="Product tour" />
34
+ * </AspectRatio>
35
+ * ```
36
+ */
37
+ export const AspectRatio = React.forwardRef(function AspectRatio({ ratio = "16/9", rounded, fit, tone, className, style, children, ...props }, ref) {
38
+ const value = parseAspectRatio(ratio) ?? 16 / 9;
39
+ return (_jsx("div", { ref: ref, "data-slot": "aspect-ratio", className: cn(aspectRatioVariants({ rounded, fit, tone }),
40
+ // The child fills the box; iframes lose their default border.
41
+ "[&>*]:absolute [&>*]:inset-0 [&>*]:size-full [&>iframe]:border-0", className), style: { aspectRatio: String(value), ...style }, ...props, children: children }));
42
+ });
@@ -0,0 +1,42 @@
1
+ import * as React from "react";
2
+ export declare const backupCodesLabels: {
3
+ title: string;
4
+ copy: string;
5
+ copied: string;
6
+ copiedAnnouncement: string;
7
+ download: string;
8
+ regenerate: string;
9
+ used: string;
10
+ remaining: string;
11
+ fileHeader: string;
12
+ };
13
+ export type BackupCodesLabels = typeof backupCodesLabels;
14
+ export interface BackupCodesProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "title" | "onCopy"> {
15
+ /** One-time recovery codes, in display order. */
16
+ codes: string[];
17
+ /** Codes already spent — struck through and announced as used. */
18
+ used?: string[];
19
+ /** Heading above the grid. Default "Backup codes"; `null` hides it (label the region yourself). */
20
+ title?: React.ReactNode;
21
+ /** Name of the downloaded text file. Default `"backup-codes.txt"`. */
22
+ filename?: string;
23
+ /** Extra first line(s) of the downloaded file (account, service). */
24
+ fileNote?: string;
25
+ /** Called after the codes were copied. */
26
+ onCopy?: (text: string) => void;
27
+ /** Replace the default download (Blob + link) — e.g. to log it. */
28
+ onDownload?: (text: string) => void;
29
+ /** Shows a "New codes" button. */
30
+ onRegenerate?: () => void;
31
+ regenerating?: boolean;
32
+ labels?: Partial<BackupCodesLabels>;
33
+ }
34
+ /**
35
+ * One-time recovery codes after two-factor enrolment: a numbered monospace grid with copy,
36
+ * download and regenerate. Used codes stay visible, struck through.
37
+ *
38
+ * ```tsx
39
+ * <BackupCodes codes={codes} used={["4K7Q-PX2M"]} onRegenerate={regenerate} />
40
+ * ```
41
+ */
42
+ export declare const BackupCodes: React.ForwardRefExoticComponent<BackupCodesProps & React.RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,67 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { Check, Copy, Download, RefreshCw } from "lucide-react";
5
+ import { cn } from "../lib/cn.js";
6
+ import { useLabels } from "../lib/labels.js";
7
+ import { useFormat } from "../lib/locale.js";
8
+ import { Button } from "./button.js";
9
+ export const backupCodesLabels = {
10
+ title: "Backup codes",
11
+ copy: "Copy",
12
+ copied: "Copied",
13
+ copiedAnnouncement: "Backup codes copied to the clipboard",
14
+ download: "Download",
15
+ regenerate: "New codes",
16
+ used: "used",
17
+ remaining: "{left} of {total} left",
18
+ fileHeader: "Backup codes — each code works once. Keep them somewhere safe.",
19
+ };
20
+ /**
21
+ * One-time recovery codes after two-factor enrolment: a numbered monospace grid with copy,
22
+ * download and regenerate. Used codes stay visible, struck through.
23
+ *
24
+ * ```tsx
25
+ * <BackupCodes codes={codes} used={["4K7Q-PX2M"]} onRegenerate={regenerate} />
26
+ * ```
27
+ */
28
+ export const BackupCodes = React.forwardRef(function BackupCodes({ codes, used = [], title, filename = "backup-codes.txt", fileNote, onCopy, onDownload, onRegenerate, regenerating, labels, className, ...props }, ref) {
29
+ const t = useLabels("backupCodes", backupCodesLabels, labels);
30
+ const f = useFormat();
31
+ const [copied, setCopied] = React.useState(false);
32
+ const usedSet = React.useMemo(() => new Set(used), [used]);
33
+ const titleId = React.useId();
34
+ const text = React.useMemo(() => [fileNote, t("fileHeader"), "", ...codes.map((c, i) => `${String(i + 1).padStart(2, " ")}. ${c}${usedSet.has(c) ? ` (${t("used")})` : ""}`)].filter((l) => l !== undefined).join("\n") + "\n", [codes, usedSet, fileNote, t]);
35
+ React.useEffect(() => {
36
+ if (!copied)
37
+ return;
38
+ const id = window.setTimeout(() => setCopied(false), 2000);
39
+ return () => window.clearTimeout(id);
40
+ }, [copied]);
41
+ const copy = async () => {
42
+ try {
43
+ await navigator.clipboard?.writeText(text);
44
+ }
45
+ catch {
46
+ /* clipboard blocked — still report so the user can select manually */
47
+ }
48
+ setCopied(true);
49
+ onCopy?.(text);
50
+ };
51
+ const download = () => {
52
+ if (onDownload)
53
+ return onDownload(text);
54
+ const url = URL.createObjectURL(new Blob([text], { type: "text/plain;charset=utf-8" }));
55
+ const a = document.createElement("a");
56
+ a.href = url;
57
+ a.download = filename;
58
+ a.click();
59
+ window.setTimeout(() => URL.revokeObjectURL(url), 0);
60
+ };
61
+ const left = codes.filter((c) => !usedSet.has(c)).length;
62
+ const heading = title === undefined ? t("title") : title;
63
+ return (_jsxs("div", { ref: ref, "data-slot": "backup-codes", role: "group", "aria-labelledby": heading ? titleId : undefined, className: cn("grid gap-3", className), ...props, children: [heading ? (_jsxs("div", { className: "flex items-baseline justify-between gap-3", children: [_jsx("h3", { id: titleId, className: "text-sm font-medium text-fg", children: heading }), _jsx("span", { className: "text-xs text-fg-muted tabular", children: t("remaining", { left: f.number(left), total: f.number(codes.length) }) })] })) : null, _jsx("ol", { className: "grid grid-cols-2 gap-x-6 gap-y-1.5 rounded-ui border border-line bg-surface-2 px-4 py-3.5 font-mono text-[13px] tabular", translate: "no", children: codes.map((code, i) => {
64
+ const spent = usedSet.has(code);
65
+ return (_jsxs("li", { "data-used": spent || undefined, className: "flex items-baseline gap-3", children: [_jsx("span", { "aria-hidden": "true", className: "w-4 text-end text-[11px] text-fg-subtle", children: i + 1 }), _jsx("span", { className: cn("tracking-wide select-all", spent ? "text-fg-subtle line-through decoration-fg-subtle" : "text-fg"), children: code }), spent ? _jsxs("span", { className: "sr-only", children: ["(", t("used"), ")"] }) : null] }, code));
66
+ }) }), _jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsxs(Button, { size: "sm", variant: "secondary", onClick: copy, children: [copied ? _jsx(Check, { "aria-hidden": "true" }) : _jsx(Copy, { "aria-hidden": "true" }), copied ? t("copied") : t("copy")] }), _jsxs(Button, { size: "sm", variant: "secondary", onClick: download, children: [_jsx(Download, { "aria-hidden": "true" }), t("download")] }), onRegenerate ? (_jsxs(Button, { size: "sm", variant: "ghost", className: "ms-auto", onClick: onRegenerate, loading: regenerating, children: [_jsx(RefreshCw, { "aria-hidden": "true" }), t("regenerate")] })) : null, _jsx("span", { role: "status", "aria-live": "polite", className: "sr-only", children: copied ? t("copiedAnnouncement") : "" })] })] }));
67
+ });
@@ -15,7 +15,7 @@ export interface BreadcrumbItemData {
15
15
  label: React.ReactNode;
16
16
  href?: string;
17
17
  icon?: React.ReactNode;
18
- /** Jump to siblings ("Companies › Acme ▾" → other companies). */
18
+ /** Jump to siblings ("Companies › Northpoint ▾" → other companies). */
19
19
  menu?: BreadcrumbMenuLink[];
20
20
  }
21
21
  export interface BreadcrumbProps extends React.HTMLAttributes<HTMLElement> {
@@ -37,7 +37,7 @@ export interface BreadcrumbProps extends React.HTMLAttributes<HTMLElement> {
37
37
  * `aria-current="page"` on the last item). Links go through the app's router `Link`.
38
38
  *
39
39
  * ```tsx
40
- * <Breadcrumb items={[{ label: "Companies", href: "/companies" }, { label: "Acme", href: "/companies/acme" }, { label: "Contacts" }]} />
40
+ * <Breadcrumb items={[{ label: "Companies", href: "/companies" }, { label: "Northpoint", href: "/companies/northpoint" }, { label: "Contacts" }]} />
41
41
  * ```
42
42
  *
43
43
  * Compound: `<Breadcrumb><BreadcrumbList><BreadcrumbItem><BreadcrumbLink href/></BreadcrumbItem><BreadcrumbSeparator/>…<BreadcrumbPage/></BreadcrumbList></Breadcrumb>`.
@@ -21,7 +21,7 @@ const SizeContext = React.createContext("md");
21
21
  * `aria-current="page"` on the last item). Links go through the app's router `Link`.
22
22
  *
23
23
  * ```tsx
24
- * <Breadcrumb items={[{ label: "Companies", href: "/companies" }, { label: "Acme", href: "/companies/acme" }, { label: "Contacts" }]} />
24
+ * <Breadcrumb items={[{ label: "Companies", href: "/companies" }, { label: "Northpoint", href: "/companies/northpoint" }, { label: "Contacts" }]} />
25
25
  * ```
26
26
  *
27
27
  * Compound: `<Breadcrumb><BreadcrumbList><BreadcrumbItem><BreadcrumbLink href/></BreadcrumbItem><BreadcrumbSeparator/>…<BreadcrumbPage/></BreadcrumbList></Breadcrumb>`.
@@ -19,6 +19,7 @@ declare const carouselLabels: {
19
19
  thumbs: string;
20
20
  empty: string;
21
21
  loading: string;
22
+ marqueePause: string;
22
23
  };
23
24
  export type CarouselLabels = typeof carouselLabels;
24
25
  export type CarouselPreset = "default" | "gallery" | "hero" | "strip";
@@ -161,10 +162,18 @@ export interface MarqueeProps extends React.HTMLAttributes<HTMLDivElement> {
161
162
  /** Fade the edges. Default `true`. */
162
163
  fade?: boolean;
163
164
  gap?: "sm" | "md" | "lg";
165
+ /**
166
+ * A small pause control (a native checkbox, works without JavaScript). Moving content that runs
167
+ * longer than five seconds needs one (WCAG 2.2.2). Default `true`.
168
+ */
169
+ controls?: boolean;
170
+ /** Accessible name of the pause control. Default "Pause scrolling" (dictionary `carousel.marqueePause`). */
171
+ pauseLabel?: string;
164
172
  }
165
173
  /**
166
- * Endless logo band in pure CSS: no JS, renders with SSR. The items are listed once for assistive
167
- * tech; a duplicate track (aria-hidden) closes the loop. Reduced motion: static, scrollable row.
174
+ * Endless logo band in pure CSS: renders with SSR. The items are listed once for assistive tech;
175
+ * a duplicate track (`aria-hidden` + `inert`, so its links never take focus) closes the loop.
176
+ * Pauses on hover/focus and with its pause control. Reduced motion: static, scrollable row.
168
177
  */
169
- export declare function Marquee({ label, duration, reverse, pauseOnHover, fade, gap, className, style, children, ...props }: MarqueeProps): React.JSX.Element;
178
+ export declare function Marquee({ label, duration, reverse, pauseOnHover, fade, gap, controls, pauseLabel, className, style, children, ...props }: MarqueeProps): React.JSX.Element;
170
179
  export {};