tiny-essentials 1.29.1 → 1.29.2

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 (128) hide show
  1. package/changelog/1/29/2.md +82 -0
  2. package/dist/v1/TinyBasicsEs.min.js +1 -1
  3. package/dist/v1/TinyEssentials.min.js +1 -1
  4. package/dist/v1/TinyFetchLoader.min.js +1 -0
  5. package/dist/v1/TinyImageLoader.min.js +1 -0
  6. package/dist/v1/TinyMediaCache.min.js +1 -0
  7. package/dist/v1/TinyMediaLoader.min.js +1 -0
  8. package/dist/v1/basics/index.cjs +5 -0
  9. package/dist/v1/basics/index.d.mts +2 -1
  10. package/dist/v1/basics/index.d.mts.map +1 -1
  11. package/dist/v1/basics/index.mjs +2 -1
  12. package/dist/v1/basics/media/youtube.cjs +275 -0
  13. package/dist/v1/basics/media/youtube.d.mts +107 -0
  14. package/dist/v1/basics/media/youtube.d.mts.map +1 -0
  15. package/dist/v1/basics/media/youtube.mjs +214 -0
  16. package/dist/v1/index.cjs +13 -0
  17. package/dist/v1/index.d.mts +6 -1
  18. package/dist/v1/index.d.mts.map +1 -1
  19. package/dist/v1/index.mjs +7 -2
  20. package/dist/v1/libs/fs/plugins/OPFS/StorageBucket.cjs +0 -1
  21. package/dist/v1/libs/fs/plugins/OPFS/StorageBucket.d.mts +0 -1
  22. package/dist/v1/libs/fs/plugins/OPFS/StorageBucket.d.mts.map +1 -1
  23. package/dist/v1/libs/fs/plugins/OPFS/StorageBucket.mjs +0 -1
  24. package/dist/v1/libs/fs/plugins/OPFS/index.cjs +0 -8
  25. package/dist/v1/libs/fs/plugins/OPFS/index.d.mts +0 -8
  26. package/dist/v1/libs/fs/plugins/OPFS/index.d.mts.map +1 -1
  27. package/dist/v1/libs/fs/plugins/OPFS/index.mjs +0 -8
  28. package/dist/v1/libs/html/TinyHtml.cjs +1 -1
  29. package/dist/v1/libs/html/TinyHtml.d.mts +2 -2
  30. package/dist/v1/libs/html/TinyHtml.d.mts.map +1 -1
  31. package/dist/v1/libs/html/TinyHtml.mjs +1 -1
  32. package/dist/v1/libs/html/loader/TinyMediaLoader.cjs +1999 -0
  33. package/dist/v1/libs/html/loader/TinyMediaLoader.d.mts +999 -0
  34. package/dist/v1/libs/html/loader/TinyMediaLoader.d.mts.map +1 -0
  35. package/dist/v1/libs/html/loader/TinyMediaLoader.mjs +1852 -0
  36. package/dist/v1/libs/html/loader/beta/formats/TinyAudioLoader.cjs +77 -0
  37. package/dist/v1/libs/html/loader/beta/formats/TinyAudioLoader.d.mts +103 -0
  38. package/dist/v1/libs/html/loader/beta/formats/TinyAudioLoader.d.mts.map +1 -0
  39. package/dist/v1/libs/html/loader/beta/formats/TinyAudioLoader.mjs +67 -0
  40. package/dist/v1/libs/html/loader/beta/formats/TinyContentLoader.cjs +630 -0
  41. package/dist/v1/libs/html/loader/beta/formats/TinyContentLoader.d.mts +138 -0
  42. package/dist/v1/libs/html/loader/beta/formats/TinyContentLoader.d.mts.map +1 -0
  43. package/dist/v1/libs/html/loader/beta/formats/TinyContentLoader.mjs +576 -0
  44. package/dist/v1/libs/html/loader/beta/formats/TinyVideoLoader.cjs +70 -0
  45. package/dist/v1/libs/html/loader/beta/formats/TinyVideoLoader.d.mts +100 -0
  46. package/dist/v1/libs/html/loader/beta/formats/TinyVideoLoader.d.mts.map +1 -0
  47. package/dist/v1/libs/html/loader/beta/formats/TinyVideoLoader.mjs +60 -0
  48. package/dist/v1/libs/html/loader/beta/probe/TinyMediaProbe.cjs +946 -0
  49. package/dist/v1/libs/html/loader/beta/probe/TinyMediaProbe.d.mts +67 -0
  50. package/dist/v1/libs/html/loader/beta/probe/TinyMediaProbe.d.mts.map +1 -0
  51. package/dist/v1/libs/html/loader/beta/probe/TinyMediaProbe.mjs +896 -0
  52. package/dist/v1/libs/html/loader/formats/TinyFetchLoader.cjs +225 -0
  53. package/dist/v1/libs/html/loader/formats/TinyFetchLoader.d.mts +149 -0
  54. package/dist/v1/libs/html/loader/formats/TinyFetchLoader.d.mts.map +1 -0
  55. package/dist/v1/libs/html/loader/formats/TinyFetchLoader.mjs +197 -0
  56. package/dist/v1/libs/html/loader/formats/TinyImageLoader.cjs +1454 -0
  57. package/dist/v1/libs/html/loader/formats/TinyImageLoader.d.mts +200 -0
  58. package/dist/v1/libs/html/loader/formats/TinyImageLoader.d.mts.map +1 -0
  59. package/dist/v1/libs/html/loader/formats/TinyImageLoader.mjs +1317 -0
  60. package/dist/v1/libs/html/loader/probe/TinyImageProbe.cjs +668 -0
  61. package/dist/v1/libs/html/loader/probe/TinyImageProbe.d.mts +83 -0
  62. package/dist/v1/libs/html/loader/probe/TinyImageProbe.d.mts.map +1 -0
  63. package/dist/v1/libs/html/loader/probe/TinyImageProbe.mjs +626 -0
  64. package/dist/v1/libs/html/loader/utils/TinyBufferReader.cjs +277 -0
  65. package/dist/v1/libs/html/loader/utils/TinyBufferReader.d.mts +118 -0
  66. package/dist/v1/libs/html/loader/utils/TinyBufferReader.d.mts.map +1 -0
  67. package/dist/v1/libs/html/loader/utils/TinyBufferReader.mjs +247 -0
  68. package/dist/v1/libs/html/loader/utils/TinyIsoBox.cjs +128 -0
  69. package/dist/v1/libs/html/loader/utils/TinyIsoBox.d.mts +49 -0
  70. package/dist/v1/libs/html/loader/utils/TinyIsoBox.d.mts.map +1 -0
  71. package/dist/v1/libs/html/loader/utils/TinyIsoBox.mjs +116 -0
  72. package/dist/v1/libs/html/loader/utils/TinyMediaCache.cjs +796 -0
  73. package/dist/v1/libs/html/loader/utils/TinyMediaCache.d.mts +354 -0
  74. package/dist/v1/libs/html/loader/utils/TinyMediaCache.d.mts.map +1 -0
  75. package/dist/v1/libs/html/loader/utils/TinyMediaCache.mjs +734 -0
  76. package/dist/v1/libs/html/loader/utils/TinyMediaMirror.cjs +302 -0
  77. package/dist/v1/libs/html/loader/utils/TinyMediaMirror.d.mts +256 -0
  78. package/dist/v1/libs/html/loader/utils/TinyMediaMirror.d.mts.map +1 -0
  79. package/dist/v1/libs/html/loader/utils/TinyMediaMirror.mjs +280 -0
  80. package/dist/v1/libs/html/loader/utils/TinyMediaProgress.cjs +194 -0
  81. package/dist/v1/libs/html/loader/utils/TinyMediaProgress.d.mts +138 -0
  82. package/dist/v1/libs/html/loader/utils/TinyMediaProgress.d.mts.map +1 -0
  83. package/dist/v1/libs/html/loader/utils/TinyMediaProgress.mjs +175 -0
  84. package/dist/v1/libs/tools/TinyPkgExportValidator.cjs +359 -55
  85. package/dist/v1/libs/tools/TinyPkgExportValidator.d.mts +64 -6
  86. package/dist/v1/libs/tools/TinyPkgExportValidator.d.mts.map +1 -1
  87. package/dist/v1/libs/tools/TinyPkgExportValidator.mjs +320 -57
  88. package/dist/v1/libs/worker/engine/TinyWebWorkerEngine.cjs +0 -1
  89. package/dist/v1/libs/worker/engine/TinyWebWorkerEngine.d.mts +0 -1
  90. package/dist/v1/libs/worker/engine/TinyWebWorkerEngine.d.mts.map +1 -1
  91. package/dist/v1/libs/worker/engine/TinyWebWorkerEngine.mjs +0 -1
  92. package/dist/v1/webTemplates/bootstrap/5.3/scss/background/_background-grid.scss +15 -0
  93. package/dist/v1/webTemplates/bootstrap/5.3/scss/components/buttons/_buttons-contrast.scss +208 -0
  94. package/dist/v1/webTemplates/bootstrap/5.3/scss/components/buttons/_buttons-ghost.scss +89 -0
  95. package/dist/v1/webTemplates/bootstrap/5.3/scss/components/icon/_cube-icon.scss +65 -0
  96. package/dist/v1/webTemplates/bootstrap/5.3/scss/components/icon/_sphere-pulse.scss +39 -0
  97. package/dist/v1/webTemplates/bootstrap/5.3/scss/themes/deepstrap/_badges.scss +90 -0
  98. package/dist/v1/webTemplates/bootstrap/5.3/scss/themes/deepstrap/_bootstrap-overrides.scss +495 -0
  99. package/dist/v1/webTemplates/bootstrap/5.3/scss/themes/deepstrap/_buttons.scss +390 -0
  100. package/dist/v1/webTemplates/bootstrap/5.3/scss/themes/deepstrap/_colors.scss +213 -0
  101. package/dist/v1/webTemplates/bootstrap/5.3/scss/themes/deepstrap/_effects.scss +153 -0
  102. package/dist/v1/webTemplates/bootstrap/5.3/scss/themes/deepstrap/_forms-tones.scss +69 -0
  103. package/dist/v1/webTemplates/bootstrap/5.3/scss/themes/deepstrap/_forms.scss +323 -0
  104. package/dist/v1/webTemplates/bootstrap/5.3/scss/themes/deepstrap/_global.scss +31 -0
  105. package/dist/v1/webTemplates/bootstrap/5.3/scss/themes/deepstrap/_links.scss +47 -0
  106. package/dist/v1/webTemplates/bootstrap/5.3/scss/themes/deepstrap/_tables.scss +25 -0
  107. package/dist/v1/webTemplates/bootstrap/5.3/scss/themes/deepstrap/_theme.scss +21 -0
  108. package/dist/v1/webTemplates/bootstrap/5.3/scss/themes/deepstrap/_tokens.scss +161 -0
  109. package/dist/v1/webTemplates/bootstrap/5.3/scss/themes/deepstrap/_utilities.scss +81 -0
  110. package/dist/v1/webTemplates/bootstrap/5.3/scss/themes/deepstrap/_variables.scss +63 -0
  111. package/dist/v1/webTemplates/bootstrap/5.3/scss/themes/deepstrap/plugins/_form-tone-mixins.scss +236 -0
  112. package/dist/v1/webTemplates/bootstrap/5.3/scss/themes/deepstrap/plugins/_sizing.scss +68 -0
  113. package/dist/v1/webTemplates/bootstrap/5.3/scss/themes/deepstrap/plugins/_tone-mixins.scss +392 -0
  114. package/dist/v1/webTemplates/bootstrap/5.3/scss/themes/deepstrap/plugins/_typography.scss +112 -0
  115. package/dist/v1/webTemplates/bootstrap/5.3/scss/themes/deepstrap/plugins/background/_tiny_gradient_1.scss +131 -0
  116. package/dist/v1/webTemplates/bootstrap/5.3/scss/themes/deepstrap/plugins/colors/_pink.scss +47 -0
  117. package/docs/v1/Exports.md +33 -2
  118. package/docs/v1/README.md +9 -0
  119. package/docs/v1/basics/youtube.md +204 -0
  120. package/docs/v1/libs/html/loader/TinyFetchLoader.md +114 -0
  121. package/docs/v1/libs/html/loader/TinyImageLoader.md +141 -0
  122. package/docs/v1/libs/html/loader/TinyMediaCache.md +166 -0
  123. package/docs/v1/libs/html/loader/TinyMediaLoader.md +300 -0
  124. package/docs/v1/libs/tools/TinyPkgExportValidator.md +55 -0
  125. package/docs/v1/webTemplates/bootstrap/5.3/DeepStrap.md +177 -0
  126. package/package.json +244 -8
  127. /package/dist/v1/webTemplates/bootstrap/5.3/scss/input/{Placeholder-Colors-Fix.scss → _placeholder-colors-fix.scss} +0 -0
  128. /package/dist/v1/webTemplates/bootstrap/5.3/scss/spacing/{Spacing-Plus.scss → _spacing-plus.scss} +0 -0
@@ -0,0 +1,390 @@
1
+ @use 'sass:list';
2
+ @use 'sass:map';
3
+
4
+ // =============================================================================
5
+ // 1. Configuration
6
+ // =============================================================================
7
+
8
+ /// Defaults merged into every `$button-families` entry.
9
+ ///
10
+ /// @type Map
11
+ /// @prop {String|null} mix - Overrides `--btn-mix`.
12
+ /// @prop {String|null} hover - Overrides `--btn-hover-amount`.
13
+ /// @prop {String|null} press - Overrides `--btn-press-amount`.
14
+ /// @prop {Boolean} seam - Draws a stronger outline edge.
15
+ /// @prop {List} variants - Which variants to emit.
16
+ $button-defaults: (
17
+ 'mix': null,
18
+ 'hover': null,
19
+ 'press': null,
20
+ 'seam': false,
21
+ 'variants': (
22
+ 'solid',
23
+ 'outline',
24
+ 'subtle',
25
+ ),
26
+ );
27
+
28
+ /// Every button family. One entry generates up to three classes:
29
+ ///
30
+ /// .btn-<name> solid
31
+ /// .btn-outline-<name> outline
32
+ /// .btn-subtle-<name> subtle
33
+ ///
34
+ /// @type Map
35
+ $button-families: (
36
+ 'primary': (
37
+ tone: 'accent',
38
+ ),
39
+ 'secondary': (
40
+ tone: 'text-muted',
41
+ ),
42
+ 'success': (
43
+ tone: 'success',
44
+ ),
45
+ 'danger': (
46
+ tone: 'error',
47
+ ),
48
+ 'warning': (
49
+ tone: 'warn',
50
+ ),
51
+ 'info': (
52
+ tone: 'info',
53
+ ),
54
+ 'light': (
55
+ tone: 'neutral-light',
56
+ mix: 'rgb(var(--ui-shade-rgb))',
57
+ hover: '92%',
58
+ press: '82%',
59
+ seam: true,
60
+ ),
61
+ 'dark': (
62
+ tone: 'neutral-dark',
63
+ mix: 'var(--ui-neutral-light)',
64
+ hover: '82%',
65
+ press: '72%',
66
+ seam: true,
67
+ ),
68
+ );
69
+
70
+ /// Ghost module configuration. Must mirror `$button-families`.
71
+ $ghost-tones: (
72
+ 'primary': var(--ui-accent),
73
+ 'secondary': var(--ui-text-muted),
74
+ 'success': var(--ui-success),
75
+ 'danger': var(--ui-error),
76
+ 'warning': var(--ui-warn),
77
+ 'info': var(--ui-info),
78
+ 'light': var(--ui-neutral-light),
79
+ 'dark': var(--ui-neutral-dark),
80
+ );
81
+
82
+ @use '../../components/buttons/_buttons-ghost.scss' with (
83
+ $tones: $ghost-tones
84
+ );
85
+
86
+ // Fail loud during development if a family is missing from the ghost map.
87
+ @each $name, $config in $button-families {
88
+ @if not map.has-key($ghost-tones, $name) {
89
+ @warn 'Button family `#{$name}` is missing from `$ghost-tones`.';
90
+ }
91
+ }
92
+
93
+ // =============================================================================
94
+ // 2. Primitives
95
+ // =============================================================================
96
+
97
+ /// Blends a theme tone into an opaque surface colour.
98
+ /// @param {String} $tone - Token suffix, without the `--ui-` prefix.
99
+ /// @param {Number} $amount - Share of the tone in the mix.
100
+ /// @param {String} $base - CSS colour the tone is blended into.
101
+ /// @return {String} An opaque `color-mix()` value.
102
+ @function solid-tint($tone, $amount: 40%, $base: var(--ui-canvas)) {
103
+ @return color-mix(in srgb, var(--ui-#{$tone}) #{$amount}, #{$base});
104
+ }
105
+
106
+ // =============================================================================
107
+ // 3. Variant mixins
108
+ // =============================================================================
109
+
110
+ /// @param {String} $tone - Token suffix, without the `--ui-` prefix.
111
+ @mixin subtle-variant($tone) {
112
+ --btn-tone: var(--ui-#{$tone});
113
+ --btn-tone-rgb: var(--ui-#{$tone}-rgb);
114
+ --bs-btn-color: var(--ui-#{$tone});
115
+ --bs-btn-hover-color: var(--ui-#{$tone});
116
+ --bs-btn-active-color: var(--ui-#{$tone});
117
+ --bs-btn-disabled-color: var(--ui-#{$tone});
118
+
119
+ --btn-border: transparent;
120
+
121
+ --btn-group-border: color-mix(in srgb, var(--ui-#{$tone}) 40%, var(--btn-group-bg));
122
+
123
+ color: var(--ui-#{$tone});
124
+ background-color: rgb(var(--ui-#{$tone}-rgb) / 0.12);
125
+
126
+ border: 1px solid var(--btn-border);
127
+
128
+ &.hover-border {
129
+ --btn-border: #{solid-tint($tone, 40%, var(--btn-group-bg, var(--ui-canvas)))};
130
+ }
131
+
132
+ &:hover:not(:disabled):not(.disabled),
133
+ &:active:not(:disabled):not(.disabled),
134
+ &.active {
135
+ border-color: var(--btn-border);
136
+ }
137
+
138
+ &:hover:not(:disabled):not(.disabled) {
139
+ --btn-glow:
140
+ 0 0 0 1px rgb(var(--ui-#{$tone}-rgb) / 0.25), 0 0 20px -6px rgb(var(--ui-#{$tone}-rgb) / 0.45);
141
+
142
+ background-color: rgb(var(--ui-#{$tone}-rgb) / 0.2);
143
+ }
144
+
145
+ &:active:not(:disabled):not(.disabled) {
146
+ background-color: rgb(var(--ui-#{$tone}-rgb) / 0.28);
147
+ }
148
+ }
149
+
150
+ /// Emits a solid variant.
151
+ ///
152
+ /// @param {String} $tone - Token suffix, without the `--ui-` prefix.
153
+ @mixin solid-variant($tone) {
154
+ --btn-tone: var(--ui-#{$tone});
155
+ --btn-tone-rgb: var(--ui-#{$tone}-rgb);
156
+ --bs-btn-color: var(--ui-on-#{$tone});
157
+ --bs-btn-hover-color: var(--ui-on-#{$tone});
158
+ --bs-btn-active-color: var(--ui-on-#{$tone});
159
+ --bs-btn-disabled-color: var(--ui-on-#{$tone});
160
+
161
+ --bs-btn-bg: var(--ui-#{$tone});
162
+ --bs-btn-border-color: var(--ui-#{$tone});
163
+ --bs-btn-hover-bg: color-mix(in srgb, var(--ui-#{$tone}) var(--btn-hover-amount), var(--btn-mix));
164
+ --bs-btn-hover-border-color: var(--bs-btn-hover-bg);
165
+ --bs-btn-active-bg: color-mix(
166
+ in srgb,
167
+ var(--ui-#{$tone}) var(--btn-press-amount),
168
+ var(--btn-mix)
169
+ );
170
+ --bs-btn-active-border-color: var(--bs-btn-active-bg);
171
+ --bs-btn-disabled-bg: var(--ui-#{$tone});
172
+ --bs-btn-disabled-border-color: var(--ui-#{$tone});
173
+ --bs-btn-focus-shadow-rgb: var(--ui-#{$tone}-rgb);
174
+
175
+ --btn-group-border: color-mix(in srgb, var(--ui-on-#{$tone}) 40%, var(--ui-#{$tone}));
176
+
177
+ --btn-fill: var(--ui-#{$tone});
178
+
179
+ color: var(--ui-on-#{$tone});
180
+ background-color: var(--btn-fill);
181
+ border-color: transparent !important;
182
+
183
+ &:hover:not(:disabled):not(.disabled) {
184
+ --btn-glow:
185
+ 0 0 20px -4px rgb(var(--ui-#{$tone}-rgb) / 0.55),
186
+ 0 0 40px -8px rgb(var(--ui-#{$tone}-rgb) / 0.35);
187
+
188
+ --btn-fill: color-mix(in srgb, var(--ui-#{$tone}) var(--btn-hover-amount), var(--btn-mix));
189
+ }
190
+
191
+ &:active:not(:disabled):not(.disabled),
192
+ &.active {
193
+ --btn-fill: color-mix(in srgb, var(--ui-#{$tone}) var(--btn-press-amount), var(--btn-mix));
194
+ }
195
+ }
196
+
197
+ /// Emits an outline variant.
198
+ ///
199
+ /// @param {String} $tone - Token suffix, without the `--ui-` prefix.
200
+ /// @param {Boolean} $seam - Draws a hairline ring so the button stays visible
201
+ /// when the tone matches the page background.
202
+ @mixin outline-variant($tone, $seam: false) {
203
+ --btn-tone: var(--ui-#{$tone});
204
+ --btn-tone-rgb: var(--ui-#{$tone}-rgb);
205
+ --bs-btn-color: var(--ui-#{$tone});
206
+ --bs-btn-hover-color: var(--ui-on-#{$tone});
207
+ --bs-btn-active-color: var(--ui-on-#{$tone});
208
+ --bs-btn-disabled-color: var(--ui-#{$tone});
209
+
210
+ --bs-btn-bg: transparent;
211
+ --bs-btn-border-color: var(--ui-#{$tone});
212
+ --bs-btn-hover-bg: var(--ui-#{$tone});
213
+ --bs-btn-hover-border-color: var(--ui-#{$tone});
214
+ --bs-btn-active-bg: color-mix(
215
+ in srgb,
216
+ var(--ui-#{$tone}) var(--btn-press-amount),
217
+ var(--btn-mix)
218
+ );
219
+ --bs-btn-active-border-color: var(--bs-btn-active-bg);
220
+ --bs-btn-disabled-bg: transparent;
221
+ --bs-btn-disabled-border-color: var(--ui-#{$tone});
222
+ --bs-btn-focus-shadow-rgb: var(--ui-#{$tone}-rgb);
223
+
224
+ --btn-group-border: color-mix(in srgb, var(--ui-#{$tone}) 40%, var(--btn-group-bg));
225
+
226
+ color: var(--ui-#{$tone});
227
+ background-color: transparent;
228
+ border-color: solid-tint($tone, 40%, var(--btn-group-bg, var(--ui-canvas)));
229
+
230
+ @if $seam {
231
+ border-color: solid-tint($tone, 70%, var(--btn-group-bg, var(--ui-canvas)));
232
+ }
233
+
234
+ &:hover:not(:disabled):not(.disabled) {
235
+ --btn-glow:
236
+ 0 0 0 1px rgb(var(--ui-#{$tone}-rgb) / 0.35), 0 0 20px -4px rgb(var(--ui-#{$tone}-rgb) / 0.55);
237
+
238
+ color: var(--ui-on-#{$tone});
239
+ background-color: var(--ui-#{$tone});
240
+ border-color: var(--ui-#{$tone});
241
+ }
242
+
243
+ &:active:not(:disabled):not(.disabled),
244
+ &.active {
245
+ color: var(--ui-on-#{$tone});
246
+ background-color: color-mix(
247
+ in srgb,
248
+ var(--ui-#{$tone}) var(--btn-press-amount),
249
+ var(--btn-mix)
250
+ );
251
+ border-color: transparent;
252
+ }
253
+ }
254
+
255
+ // =============================================================================
256
+ // 4. Base
257
+ // =============================================================================
258
+
259
+ .btn {
260
+ --bs-btn-border-radius: var(--bs-border-radius-sm);
261
+ --bs-btn-disabled-opacity: 0.4;
262
+ --btn-tone: var(--ui-accent);
263
+ --btn-tone-rgb: var(--ui-accent-rgb);
264
+ --btn-glow: none;
265
+
266
+ --btn-mix: var(--ui-btn-mix);
267
+ --btn-hover-amount: 76%;
268
+ --btn-press-amount: 68%;
269
+
270
+ border: 1px solid var(--bs-btn-border-color, transparent);
271
+ transition:
272
+ background-color var(--ui-duration) var(--ui-ease),
273
+ border-color var(--ui-duration) var(--ui-ease),
274
+ color var(--ui-duration) var(--ui-ease),
275
+ box-shadow var(--ui-duration) var(--ui-ease);
276
+
277
+ .badge {
278
+ transition:
279
+ color var(--ui-duration) var(--ui-ease),
280
+ background-color var(--ui-duration) var(--ui-ease),
281
+ border-color var(--ui-duration) var(--ui-ease);
282
+ }
283
+
284
+ &:active:not(:disabled):not(.disabled) {
285
+ transition-duration: 60ms;
286
+ }
287
+
288
+ &:focus-visible {
289
+ outline: 2px solid var(--btn-tone);
290
+ outline-offset: 2px;
291
+ }
292
+
293
+ &:disabled,
294
+ &.disabled {
295
+ pointer-events: none;
296
+ }
297
+ }
298
+
299
+ // =============================================================================
300
+ // 5. Generator
301
+ // =============================================================================
302
+
303
+ /// Emits the `--btn-*` overrides for a single family.
304
+ ///
305
+ /// @param {Map} $config - Merged `$button-families` entry.
306
+ @mixin button-overrides($config) {
307
+ $mix: map.get($config, 'mix');
308
+ $hover: map.get($config, 'hover');
309
+ $press: map.get($config, 'press');
310
+
311
+ @if $mix != null {
312
+ --btn-mix: #{$mix};
313
+ }
314
+
315
+ @if $hover != null {
316
+ --btn-hover-amount: #{$hover};
317
+ }
318
+
319
+ @if $press != null {
320
+ --btn-press-amount: #{$press};
321
+ }
322
+ }
323
+
324
+ /// Emits the variants for a single family.
325
+ ///
326
+ /// @param {String} $name - Class suffix, e.g. `primary`.
327
+ /// @param {Map} $config - Entry from `$button-families`.
328
+ @mixin button-family($name, $config) {
329
+ $config: map.merge($button-defaults, $config);
330
+ $tone: map.get($config, 'tone');
331
+ $seam: map.get($config, 'seam');
332
+ $variants: map.get($config, 'variants');
333
+
334
+ @if list.index($variants, 'solid') {
335
+ .btn-#{$name} {
336
+ @include solid-variant($tone);
337
+ @include button-overrides($config);
338
+ }
339
+ }
340
+
341
+ @if list.index($variants, 'outline') {
342
+ .btn-outline-#{$name} {
343
+ @include outline-variant($tone, $seam: $seam);
344
+ @include button-overrides($config);
345
+ }
346
+ }
347
+
348
+ @if list.index($variants, 'subtle') {
349
+ .btn-subtle-#{$name} {
350
+ @include subtle-variant($tone);
351
+ @include button-overrides($config);
352
+ }
353
+ }
354
+ }
355
+
356
+ @each $name, $config in $button-families {
357
+ @include button-family($name, $config);
358
+ }
359
+
360
+ // =============================================================================
361
+ // 6. Utilities
362
+ // =============================================================================
363
+
364
+ .btn-lighting {
365
+ &:hover:not(:disabled):not(.disabled) {
366
+ box-shadow: var(--btn-glow);
367
+ }
368
+ }
369
+
370
+ .btn-group,
371
+ .btn-group-vertical {
372
+ --btn-group-bg: var(--ui-canvas);
373
+
374
+ > .btn {
375
+ position: relative;
376
+ border-width: 1px;
377
+ border-style: solid;
378
+ }
379
+
380
+ > .btn:hover:not(:disabled):not(.disabled),
381
+ > .btn:focus-visible:not(:disabled):not(.disabled) {
382
+ z-index: 1;
383
+ }
384
+
385
+ > .btn.active,
386
+ > .btn:active:not(:disabled):not(.disabled),
387
+ > .btn-check:checked + .btn {
388
+ z-index: 2;
389
+ }
390
+ }
@@ -0,0 +1,213 @@
1
+ @use 'sass:map';
2
+ @use 'sass:string';
3
+
4
+ // ---------------------------------------------------------------- 1. palette --
5
+ /// Raw colours. Keys describe the hue, never the role.
6
+ $palette: (
7
+ // Neutral ramp, dark end.
8
+ 'slate-950': #0b0e14,
9
+ 'slate-900': #10141d,
10
+ 'slate-850': #151a25,
11
+ 'slate-800': #1c2230,
12
+ 'slate-700': #2a3243,
13
+ 'slate-600': #3b4557,
14
+ 'slate-400': #6b7688,
15
+ 'slate-200': #b6bfce,
16
+ 'slate-050': #e8ecf3,
17
+
18
+ // Neutral ramp, light end.
19
+ 'paper-000': #ffffff,
20
+ 'paper-050': #f7f9fd,
21
+ 'paper-100': #f4f6fb,
22
+ 'paper-200': #dde3ee,
23
+ 'paper-300': #c3ccdd,
24
+ 'ink-000': #000000,
25
+ 'ink-900': #0d1220,
26
+ 'ink-700': #3a4459,
27
+
28
+ // Accents.
29
+ 'indigo-700': #3f5fe0,
30
+ 'indigo-600': #5c7bf5,
31
+ 'indigo-500': #6c8cff,
32
+ 'indigo-400': #8aa2ff,
33
+ 'green-500': #3ddc97,
34
+ 'green-700': #0f8f5f,
35
+ 'red-500': #ff6b81,
36
+ 'red-700': #cf2445,
37
+ 'amber-500': #ffc46b,
38
+ 'amber-700': #a56200,
39
+ 'cyan-500': #5fd3f3,
40
+ 'cyan-700': #0a7fa5,
41
+
42
+ // Foreground inks. Sit on top of a filled tone; never used as a background.
43
+ 'on-accent': #080b11,
44
+ 'on-success': #04140d,
45
+ 'on-error': #1a0308,
46
+ 'on-warn': #1a1200,
47
+ 'on-info': #04141a,
48
+
49
+ // Cool dark used by the light theme so shadows do not read as grey.
50
+ 'shadow-slate': #1e293b
51
+ ) !default;
52
+
53
+ /// Returns a raw colour from the palette.
54
+ ///
55
+ /// @param {String} $key - Palette key, e.g. `slate-900`.
56
+ /// @returns {Color} The raw colour value.
57
+ @function palette($key) {
58
+ @if not map.has-key($palette, $key) {
59
+ @error 'Unknown palette key: #{$key}';
60
+ }
61
+
62
+ @return map.get($palette, $key);
63
+ }
64
+
65
+ // ---------------------------------------------------------------- 2. themes --
66
+ $theme-dark: (
67
+ 'canvas': palette('slate-950'),
68
+ 'surface': palette('slate-900'),
69
+ 'surface-raised': palette('slate-850'),
70
+ 'input': palette('slate-800'),
71
+ 'border': palette('slate-700'),
72
+ 'border-strong': palette('slate-600'),
73
+ 'text': palette('slate-200'),
74
+ 'text-muted': palette('slate-400'),
75
+ 'heading': palette('slate-050'),
76
+ 'accent': palette('indigo-500'),
77
+ 'accent-soft': palette('indigo-400'),
78
+ 'success': palette('green-500'),
79
+ 'error': palette('red-500'),
80
+ 'warn': palette('amber-500'),
81
+ 'info': palette('cyan-500'),
82
+ ) !default;
83
+
84
+ $theme-light: (
85
+ 'canvas': palette('paper-100'),
86
+ 'surface': palette('paper-000'),
87
+ 'surface-raised': palette('paper-050'),
88
+ 'input': palette('paper-000'),
89
+ 'border': palette('paper-200'),
90
+ 'border-strong': palette('paper-300'),
91
+ 'text': palette('ink-700'),
92
+ 'text-muted': palette('slate-400'),
93
+ 'heading': palette('ink-900'),
94
+ 'accent': palette('indigo-700'),
95
+ 'accent-soft': palette('indigo-600'),
96
+ 'success': palette('green-700'),
97
+ 'error': palette('red-700'),
98
+ 'warn': palette('amber-700'),
99
+ 'info': palette('cyan-700'),
100
+ ) !default;
101
+
102
+ // ------------------------------------------------------------ 3. foreground --
103
+ $on-dark: (
104
+ 'accent': palette('on-accent'),
105
+ 'success': palette('on-success'),
106
+ 'error': palette('on-error'),
107
+ 'warn': palette('on-warn'),
108
+ 'info': palette('on-info'),
109
+ 'text-muted': palette('paper-000'),
110
+ ) !default;
111
+
112
+ $on-light: (
113
+ 'accent': palette('paper-000'),
114
+ 'success': palette('paper-000'),
115
+ 'error': palette('paper-000'),
116
+ 'warn': palette('paper-000'),
117
+ 'info': palette('paper-000'),
118
+ 'text-muted': palette('paper-000'),
119
+ ) !default;
120
+
121
+ $subtle-tokens: (
122
+ 'primary': 'accent',
123
+ 'secondary': 'text-muted',
124
+ 'success': 'success',
125
+ 'danger': 'error',
126
+ 'warning': 'warn',
127
+ 'info': 'info',
128
+ ) !default;
129
+
130
+ // ------------------------------------------------------------- 4. constants --
131
+ $constants: (
132
+ // Backdrop behind modals.
133
+ 'scrim': #05070b,
134
+ // Chevron inside `.form-select` and `.accordion-button`.
135
+ 'control-icon': palette('slate-400'),
136
+ 'control-icon-active': palette('indigo-500'),
137
+ // Active carousel indicator.
138
+ 'carousel-indicator': palette('indigo-500')
139
+ ) !default;
140
+
141
+ $shadow: (
142
+ 'dark': palette('ink-000'),
143
+ 'light': palette('shadow-slate'),
144
+ ) !default;
145
+
146
+ $scrims: (
147
+ 'dark': (
148
+ 'base': palette('ink-000'),
149
+ 'caption': palette('paper-000'),
150
+ 'indicator': palette('paper-000'),
151
+ 'ink': palette('paper-000'),
152
+ ),
153
+ 'light': (
154
+ 'base': palette('paper-000'),
155
+ 'caption': theme-color('text', 'light'),
156
+ 'indicator': palette('slate-950'),
157
+ 'ink': palette('ink-000'),
158
+ ),
159
+ ) !default;
160
+
161
+ /// @param {String} $theme - `dark` or `light`.
162
+ /// @param {String} $role - `base`, `caption`, `indicator` or `ink`.
163
+ /// @returns {Color} The scrim colour.
164
+ @function scrim($theme, $role) {
165
+ $map: map.get($scrims, $theme);
166
+
167
+ @if not map.has-key($map, $role) {
168
+ @error 'Unknown scrim role: #{$role}';
169
+ }
170
+
171
+ @return map.get($map, $role);
172
+ }
173
+
174
+ // --------------------------------------------------------------- accessors --
175
+ /// @param {String} $name - Key in `$constants`.
176
+ /// @returns {Color} The constant value.
177
+ @function ui-color($name) {
178
+ @if not map.has-key($constants, $name) {
179
+ @error 'Unknown colour constant: #{$name}';
180
+ }
181
+
182
+ @return map.get($constants, $name);
183
+ }
184
+
185
+ $_themes: (
186
+ 'dark': $theme-dark,
187
+ 'light': $theme-light,
188
+ );
189
+
190
+ /// @param {String} $role - Semantic role, e.g. `canvas`.
191
+ /// @param {String} $theme - `dark` or `light`.
192
+ /// @returns {Color} The role colour for the given theme.
193
+ @function theme-color($role, $theme: 'dark') {
194
+ @if not map.has-key($_themes, $theme) {
195
+ @error 'Unknown theme: #{$theme}';
196
+ }
197
+
198
+ $map: map.get($_themes, $theme);
199
+
200
+ @if not map.has-key($map, $role) {
201
+ @error 'Unknown colour role: #{$role}';
202
+ }
203
+
204
+ @return map.get($map, $role);
205
+ }
206
+
207
+ /// URL-encoded hex, for inline SVG data URIs.
208
+ ///
209
+ /// @param {String} $name - Key in `$constants`.
210
+ /// @returns {String} `%23rrggbb`.
211
+ @function svg-color($name) {
212
+ @return '%23' + string.slice('#{ui-color($name)}', 2);
213
+ }