@gitlab/ui 137.3.1 → 138.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/dist/components/base/alert/alert.js +0 -1
  2. package/dist/components/base/drawer/drawer.js +0 -1
  3. package/dist/components/base/filtered_search/filtered_search_token_segment.js +0 -1
  4. package/dist/components/base/form/form_group/form_group.js +0 -1
  5. package/dist/components/base/modal/modal.js +1 -5
  6. package/dist/components/base/new_dropdowns/base_dropdown/dropdown_container.js +1 -1
  7. package/dist/components/base/new_dropdowns/disclosure/disclosure_dropdown.js +1 -3
  8. package/dist/components/base/toast/index.js +1 -1
  9. package/dist/components/base/toggle/toggle.js +0 -1
  10. package/dist/components/mixins/tooltip_mixin.js +1 -1
  11. package/dist/index.css +2 -2
  12. package/dist/index.css.map +1 -1
  13. package/dist/tailwind.css +1 -1
  14. package/dist/tailwind.css.map +1 -1
  15. package/dist/tokens/build/js/tokens.dark.js +299 -299
  16. package/dist/tokens/build/js/tokens.js +302 -302
  17. package/dist/utils/confetti/confetti.js +189 -0
  18. package/dist/utils/confetti/constants.js +36 -0
  19. package/dist/utils/confetti/field.js +114 -0
  20. package/dist/utils/confetti/palette.js +6 -0
  21. package/dist/utils/confetti/particles.js +92 -0
  22. package/dist/utils/matrix/columns.js +54 -0
  23. package/dist/utils/matrix/constants.js +19 -0
  24. package/dist/utils/matrix/matrix.js +157 -0
  25. package/dist/utils/matrix/palette.js +9 -0
  26. package/dist/utils.js +2 -0
  27. package/dist/vendor/bootstrap-vue/src/components/popover/helpers/bv-popover-template.js +4 -2
  28. package/dist/vendor/bootstrap-vue/src/components/tooltip/helpers/bv-tooltip-template.js +3 -1
  29. package/package.json +3 -2
  30. package/src/components/base/alert/alert.vue +0 -1
  31. package/src/components/base/drawer/drawer.vue +0 -1
  32. package/src/components/base/filtered_search/filtered_search_token_segment.vue +0 -1
  33. package/src/components/base/form/form_group/form_group.vue +0 -2
  34. package/src/components/base/form/form_select/form_select.vue +0 -1
  35. package/src/components/base/modal/modal.vue +0 -3
  36. package/src/components/base/new_dropdowns/base_dropdown/dropdown_container.js +1 -1
  37. package/src/components/base/new_dropdowns/disclosure/disclosure_dropdown.vue +0 -1
  38. package/src/components/base/tabs/tabs/scrollable_tabs.vue +0 -1
  39. package/src/components/base/tabs/tabs/tabs.vue +0 -1
  40. package/src/components/base/toast/index.js +1 -1
  41. package/src/components/base/toggle/toggle.vue +0 -1
  42. package/src/components/charts/heatmap/index.js +1 -1
  43. package/src/components/mixins/tooltip_mixin.js +1 -1
  44. package/src/tokens/build/css/tokens.css +74 -74
  45. package/src/tokens/build/css/tokens.dark.css +70 -70
  46. package/src/tokens/build/docs/tokens-tailwind-docs.dark.json +303 -303
  47. package/src/tokens/build/docs/tokens-tailwind-docs.json +323 -323
  48. package/src/tokens/build/figma/constants.dark.json +207 -207
  49. package/src/tokens/build/figma/constants.json +207 -207
  50. package/src/tokens/build/figma/mode.dark.json +37 -37
  51. package/src/tokens/build/figma/mode.json +35 -35
  52. package/src/tokens/build/js/tokens.dark.js +299 -300
  53. package/src/tokens/build/js/tokens.js +302 -303
  54. package/src/tokens/build/json/tokens.dark.json +369 -369
  55. package/src/tokens/build/json/tokens.json +376 -376
  56. package/src/tokens/build/scss/_tokens.dark.scss +70 -70
  57. package/src/tokens/build/scss/_tokens.scss +74 -74
  58. package/src/tokens/constant/color.blue.tokens.json +39 -39
  59. package/src/tokens/constant/color.green.tokens.json +41 -41
  60. package/src/tokens/constant/color.orange.tokens.json +43 -43
  61. package/src/tokens/constant/color.purple.tokens.json +40 -40
  62. package/src/tokens/constant/color.red.tokens.json +44 -44
  63. package/src/tokens/contextual/avatar.tokens.json +13 -13
  64. package/src/tokens/contextual/button.tokens.json +22 -22
  65. package/src/tokens/contextual/chart.tokens.json +3 -3
  66. package/src/tokens/semantic/action.tokens.json +18 -18
  67. package/src/utils/confetti/confetti.js +191 -0
  68. package/src/utils/confetti/constants.js +42 -0
  69. package/src/utils/confetti/field.js +134 -0
  70. package/src/utils/confetti/palette.js +15 -0
  71. package/src/utils/confetti/particles.js +98 -0
  72. package/src/utils/matrix/columns.js +53 -0
  73. package/src/utils/matrix/constants.js +19 -0
  74. package/src/utils/matrix/matrix.js +185 -0
  75. package/src/utils/matrix/palette.js +18 -0
  76. package/src/utils.js +2 -0
  77. package/src/vendor/bootstrap-vue/src/components/popover/helpers/bv-popover-template.js +7 -2
  78. package/src/vendor/bootstrap-vue/src/components/tooltip/helpers/bv-tooltip-template.js +2 -1
  79. package/translations.js +1 -1
@@ -5,12 +5,12 @@
5
5
  "$value": {
6
6
  "colorSpace": "srgb",
7
7
  "components": [
8
- 0.9882352941176471,
9
- 0.9450980392156862,
10
- 0.9372549019607843
8
+ 0.996078431372549,
9
+ 0.9333333333333333,
10
+ 0.9411764705882353
11
11
  ],
12
12
  "alpha": 1,
13
- "hex": "#fcf1ef"
13
+ "hex": "#feeef0"
14
14
  },
15
15
  "$type": "color",
16
16
  "$extensions": {
@@ -21,12 +21,12 @@
21
21
  "$value": {
22
22
  "colorSpace": "srgb",
23
23
  "components": [
24
- 0.9921568627450981,
25
- 0.8313725490196079,
26
- 0.803921568627451
24
+ 1,
25
+ 0.8274509803921568,
26
+ 0.8431372549019608
27
27
  ],
28
28
  "alpha": 1,
29
- "hex": "#fdd4cd"
29
+ "hex": "#ffd3d7"
30
30
  },
31
31
  "$type": "color",
32
32
  "$extensions": {
@@ -37,12 +37,12 @@
37
37
  "$value": {
38
38
  "colorSpace": "srgb",
39
39
  "components": [
40
- 0.9882352941176471,
41
- 0.7098039215686275,
42
- 0.6666666666666666
40
+ 1,
41
+ 0.6862745098039216,
42
+ 0.7215686274509804
43
43
  ],
44
44
  "alpha": 1,
45
- "hex": "#fcb5aa"
45
+ "hex": "#ffafb8"
46
46
  },
47
47
  "$type": "color",
48
48
  "$extensions": {
@@ -53,12 +53,12 @@
53
53
  "$value": {
54
54
  "colorSpace": "srgb",
55
55
  "components": [
56
- 0.9647058823529412,
57
- 0.5019607843137255,
58
- 0.42745098039215684
56
+ 0.9882352941176471,
57
+ 0.4745098039215686,
58
+ 0.5333333333333333
59
59
  ],
60
60
  "alpha": 1,
61
- "hex": "#f6806d"
61
+ "hex": "#fc7988"
62
62
  },
63
63
  "$type": "color",
64
64
  "$extensions": {
@@ -69,12 +69,12 @@
69
69
  "$value": {
70
70
  "colorSpace": "srgb",
71
71
  "components": [
72
- 0.9254901960784314,
73
- 0.34901960784313724,
74
- 0.2549019607843137
72
+ 0.9450980392156862,
73
+ 0.3176470588235294,
74
+ 0.40784313725490196
75
75
  ],
76
76
  "alpha": 1,
77
- "hex": "#ec5941"
77
+ "hex": "#f15168"
78
78
  },
79
79
  "$type": "color",
80
80
  "$extensions": {
@@ -85,12 +85,12 @@
85
85
  "$value": {
86
86
  "colorSpace": "srgb",
87
87
  "components": [
88
- 0.8666666666666667,
89
- 0.16862745098039217,
90
- 0.054901960784313725
88
+ 0.8705882352941177,
89
+ 0.11372549019607843,
90
+ 0.29411764705882354
91
91
  ],
92
92
  "alpha": 1,
93
- "hex": "#dd2b0e"
93
+ "hex": "#de1d4b"
94
94
  },
95
95
  "$type": "color",
96
96
  "$extensions": {
@@ -101,12 +101,12 @@
101
101
  "$value": {
102
102
  "colorSpace": "srgb",
103
103
  "components": [
104
- 0.7529411764705882,
105
- 0.1843137254901961,
106
- 0.07058823529411765
104
+ 0.7725490196078432,
105
+ 0.12549019607843137,
106
+ 0.25882352941176473
107
107
  ],
108
108
  "alpha": 1,
109
- "hex": "#c02f12"
109
+ "hex": "#c52042"
110
110
  },
111
111
  "$type": "color",
112
112
  "$extensions": {
@@ -117,12 +117,12 @@
117
117
  "$value": {
118
118
  "colorSpace": "srgb",
119
119
  "components": [
120
- 0.6392156862745098,
121
- 0.17254901960784313,
122
- 0.07058823529411765
120
+ 0.6745098039215687,
121
+ 0.12549019607843137,
122
+ 0.22745098039215686
123
123
  ],
124
124
  "alpha": 1,
125
- "hex": "#a32c12"
125
+ "hex": "#ac203a"
126
126
  },
127
127
  "$type": "color",
128
128
  "$extensions": {
@@ -133,12 +133,12 @@
133
133
  "$value": {
134
134
  "colorSpace": "srgb",
135
135
  "components": [
136
- 0.5058823529411764,
137
- 0.15294117647058825,
138
- 0.07450980392156863
136
+ 0.5372549019607843,
137
+ 0.10980392156862745,
138
+ 0.1843137254901961
139
139
  ],
140
140
  "alpha": 1,
141
- "hex": "#812713"
141
+ "hex": "#891c2f"
142
142
  },
143
143
  "$type": "color",
144
144
  "$extensions": {
@@ -149,12 +149,12 @@
149
149
  "$value": {
150
150
  "colorSpace": "srgb",
151
151
  "components": [
152
- 0.34509803921568627,
153
- 0.12549019607843137,
154
- 0.0784313725490196
152
+ 0.39215686274509803,
153
+ 0.09803921568627451,
154
+ 0.1450980392156863
155
155
  ],
156
156
  "alpha": 1,
157
- "hex": "#582014"
157
+ "hex": "#641925"
158
158
  },
159
159
  "$type": "color",
160
160
  "$extensions": {
@@ -165,12 +165,12 @@
165
165
  "$value": {
166
166
  "colorSpace": "srgb",
167
167
  "components": [
168
- 0.24313725490196078,
169
- 0.10196078431372549,
170
- 0.0784313725490196
168
+ 0.2823529411764706,
169
+ 0.08235294117647059,
170
+ 0.11372549019607843
171
171
  ],
172
172
  "alpha": 1,
173
- "hex": "#3e1a14"
173
+ "hex": "#48151d"
174
174
  },
175
175
  "$type": "color",
176
176
  "$extensions": {
@@ -161,9 +161,9 @@
161
161
  "$value": {
162
162
  "colorSpace": "srgb",
163
163
  "components": [
164
- 0.9882352941176471,
165
- 0.7098039215686275,
166
- 0.6666666666666666
164
+ 1,
165
+ 0.6862745098039216,
166
+ 0.7215686274509804
167
167
  ],
168
168
  "alpha": 0.23921568627450981
169
169
  },
@@ -180,9 +180,9 @@
180
180
  "$value": {
181
181
  "colorSpace": "srgb",
182
182
  "components": [
183
- 0.796078431372549,
184
- 0.7333333333333333,
185
- 0.9490196078431372
183
+ 0.788235294117647,
184
+ 0.7450980392156863,
185
+ 0.9372549019607843
186
186
  ],
187
187
  "alpha": 0.23921568627450981
188
188
  },
@@ -200,8 +200,8 @@
200
200
  "colorSpace": "srgb",
201
201
  "components": [
202
202
  0.615686274509804,
203
- 0.7803921568627451,
204
- 0.9450980392156862
203
+ 0.7843137254901961,
204
+ 0.9490196078431372
205
205
  ],
206
206
  "alpha": 0.23921568627450981
207
207
  },
@@ -218,9 +218,9 @@
218
218
  "$value": {
219
219
  "colorSpace": "srgb",
220
220
  "components": [
221
- 0.5686274509803921,
221
+ 0.5176470588235295,
222
222
  0.8313725490196079,
223
- 0.6588235294117647
223
+ 0.7137254901960784
224
224
  ],
225
225
  "alpha": 0.23921568627450981
226
226
  },
@@ -237,9 +237,9 @@
237
237
  "$value": {
238
238
  "colorSpace": "srgb",
239
239
  "components": [
240
- 0.9137254901960784,
241
- 0.7450980392156863,
242
- 0.4549019607843137
240
+ 0.9686274509803922,
241
+ 0.7254901960784313,
242
+ 0.3176470588235294
243
243
  ],
244
244
  "alpha": 0.23921568627450981
245
245
  },
@@ -867,8 +867,8 @@
867
867
  "color": {
868
868
  "default": {
869
869
  "$value": {
870
- "default": "{color.red.500}",
871
- "dark": "{color.red.300}"
870
+ "default": "{color.red.600}",
871
+ "dark": "{color.red.400}"
872
872
  },
873
873
  "$type": "color",
874
874
  "$description": "Used for the background of a danger (destructive) primary button in the default state.",
@@ -881,8 +881,8 @@
881
881
  },
882
882
  "hover": {
883
883
  "$value": {
884
- "default": "{color.red.600}",
885
- "dark": "{color.red.200}"
884
+ "default": "{color.red.700}",
885
+ "dark": "{color.red.300}"
886
886
  },
887
887
  "$type": "color",
888
888
  "$description": "Used for the background of a danger (destructive) primary button in the hover state.",
@@ -906,8 +906,8 @@
906
906
  },
907
907
  "active": {
908
908
  "$value": {
909
- "default": "{color.red.800}",
910
- "dark": "{color.red.400}"
909
+ "default": "{color.red.900}",
910
+ "dark": "{color.red.200}"
911
911
  },
912
912
  "$type": "color",
913
913
  "$description": "Used for the background of a danger (destructive) primary button in the active state.",
@@ -924,7 +924,7 @@
924
924
  "color": {
925
925
  "default": {
926
926
  "$value": {
927
- "default": "{color.red.600}",
927
+ "default": "{color.red.700}",
928
928
  "dark": "{color.alpha.0}"
929
929
  },
930
930
  "$type": "color",
@@ -937,7 +937,7 @@
937
937
  },
938
938
  "hover": {
939
939
  "$value": {
940
- "default": "{color.red.800}",
940
+ "default": "{color.red.900}",
941
941
  "dark": "{color.alpha.0}"
942
942
  },
943
943
  "$type": "color",
@@ -960,7 +960,7 @@
960
960
  },
961
961
  "active": {
962
962
  "$value": {
963
- "default": "{color.red.900}",
963
+ "default": "{color.red.950}",
964
964
  "dark": "{color.alpha.0}"
965
965
  },
966
966
  "$type": "color",
@@ -979,7 +979,7 @@
979
979
  "color": {
980
980
  "default": {
981
981
  "$value": {
982
- "default": "{color.red.500}",
982
+ "default": "{color.red.600}",
983
983
  "dark": "{color.red.100}"
984
984
  },
985
985
  "$type": "color",
@@ -993,7 +993,7 @@
993
993
  },
994
994
  "hover": {
995
995
  "$value": {
996
- "default": "{color.red.700}",
996
+ "default": "{color.red.800}",
997
997
  "dark": "{color.red.50}"
998
998
  },
999
999
  "$type": "color",
@@ -1040,9 +1040,9 @@
1040
1040
  "dark": {
1041
1041
  "colorSpace": "srgb",
1042
1042
  "components": [
1043
- 0.9254901960784314,
1044
- 0.34901960784313724,
1045
- 0.2549019607843137
1043
+ 0.9450980392156862,
1044
+ 0.3176470588235294,
1045
+ 0.40784313725490196
1046
1046
  ],
1047
1047
  "alpha": 0.4
1048
1048
  }
@@ -1062,9 +1062,9 @@
1062
1062
  "dark": {
1063
1063
  "colorSpace": "srgb",
1064
1064
  "components": [
1065
- 0.9254901960784314,
1066
- 0.34901960784313724,
1067
- 0.2549019607843137
1065
+ 0.9450980392156862,
1066
+ 0.3176470588235294,
1067
+ 0.40784313725490196
1068
1068
  ],
1069
1069
  "alpha": 0.64
1070
1070
  }
@@ -1095,9 +1095,9 @@
1095
1095
  "dark": {
1096
1096
  "colorSpace": "srgb",
1097
1097
  "components": [
1098
- 0.9254901960784314,
1099
- 0.34901960784313724,
1100
- 0.2549019607843137
1098
+ 0.9450980392156862,
1099
+ 0.3176470588235294,
1100
+ 0.40784313725490196
1101
1101
  ],
1102
1102
  "alpha": 0.32
1103
1103
  }
@@ -1117,7 +1117,7 @@
1117
1117
  "color": {
1118
1118
  "default": {
1119
1119
  "$value": {
1120
- "default": "{color.red.500}",
1120
+ "default": "{color.red.600}",
1121
1121
  "dark": "{color.alpha.0}"
1122
1122
  },
1123
1123
  "$type": "color",
@@ -1130,7 +1130,7 @@
1130
1130
  },
1131
1131
  "hover": {
1132
1132
  "$value": {
1133
- "default": "{color.red.700}",
1133
+ "default": "{color.red.800}",
1134
1134
  "dark": "{color.alpha.0}"
1135
1135
  },
1136
1136
  "$type": "color",
@@ -47,9 +47,9 @@
47
47
  "$value": {
48
48
  "colorSpace": "srgb",
49
49
  "components": [
50
- 0.8666666666666667,
51
- 0.16862745098039217,
52
- 0.054901960784313725
50
+ 0.8705882352941177,
51
+ 0.11372549019607843,
52
+ 0.29411764705882354
53
53
  ],
54
54
  "alpha": 0.1
55
55
  },
@@ -602,18 +602,18 @@
602
602
  "default": {
603
603
  "colorSpace": "srgb",
604
604
  "components": [
605
- 0.9607843137254902,
606
- 0.4980392156862745,
607
- 0.4235294117647059
605
+ 0.8705882352941177,
606
+ 0.11372549019607843,
607
+ 0.29411764705882354
608
608
  ],
609
609
  "alpha": 0
610
610
  },
611
611
  "dark": {
612
612
  "colorSpace": "srgb",
613
613
  "components": [
614
- 0.9254901960784314,
615
- 0.34901960784313724,
616
- 0.2549019607843137
614
+ 0.9450980392156862,
615
+ 0.3176470588235294,
616
+ 0.40784313725490196
617
617
  ],
618
618
  "alpha": 0
619
619
  }
@@ -632,18 +632,18 @@
632
632
  "default": {
633
633
  "colorSpace": "srgb",
634
634
  "components": [
635
- 0.9607843137254902,
636
- 0.4980392156862745,
637
- 0.4235294117647059
635
+ 0.8705882352941177,
636
+ 0.11372549019607843,
637
+ 0.29411764705882354
638
638
  ],
639
639
  "alpha": 0.16
640
640
  },
641
641
  "dark": {
642
642
  "colorSpace": "srgb",
643
643
  "components": [
644
- 0.9254901960784314,
645
- 0.34901960784313724,
646
- 0.2549019607843137
644
+ 0.9450980392156862,
645
+ 0.3176470588235294,
646
+ 0.40784313725490196
647
647
  ],
648
648
  "alpha": 0.4
649
649
  }
@@ -673,18 +673,18 @@
673
673
  "default": {
674
674
  "colorSpace": "srgb",
675
675
  "components": [
676
- 0.6823529411764706,
677
- 0.09411764705882353,
678
- 0
676
+ 0.6745098039215687,
677
+ 0.12549019607843137,
678
+ 0.22745098039215686
679
679
  ],
680
680
  "alpha": 0.24
681
681
  },
682
682
  "dark": {
683
683
  "colorSpace": "srgb",
684
684
  "components": [
685
- 0.9254901960784314,
686
- 0.34901960784313724,
687
- 0.2549019607843137
685
+ 0.9450980392156862,
686
+ 0.3176470588235294,
687
+ 0.40784313725490196
688
688
  ],
689
689
  "alpha": 0.16
690
690
  }
@@ -0,0 +1,191 @@
1
+ import { COVERAGE_RAMP } from './palette';
2
+ import { createPieces, advancePiece } from './particles';
3
+ import { createField } from './field';
4
+ import { CANVAS_Z_INDEX, DEFAULT_DURATION, FADE_OUT_DURATION, MAX_FRAME_DELTA } from './constants';
5
+
6
+ const noop = () => {};
7
+
8
+ const RUNNING_ATTRIBUTE = 'data-confetti';
9
+
10
+ const measureStage = (boundary) => {
11
+ const rect =
12
+ boundary instanceof Element
13
+ ? boundary.getBoundingClientRect()
14
+ : { left: 0, top: 0, width: window.innerWidth, height: window.innerHeight };
15
+
16
+ return { x: rect.left, y: rect.top, width: rect.width, height: rect.height };
17
+ };
18
+
19
+ const stagePoint = (element, stage) => {
20
+ if (!(element instanceof Element)) {
21
+ return null;
22
+ }
23
+
24
+ const rect = element.getBoundingClientRect();
25
+
26
+ return {
27
+ x: rect.left + rect.width / 2 - stage.x,
28
+ y: rect.top + rect.height / 2 - stage.y,
29
+ };
30
+ };
31
+
32
+ const createCanvas = () => {
33
+ const canvas = document.createElement('canvas');
34
+
35
+ canvas.setAttribute('aria-hidden', 'true');
36
+ canvas.setAttribute(RUNNING_ATTRIBUTE, '');
37
+ Object.assign(canvas.style, {
38
+ position: 'fixed',
39
+ inset: '0',
40
+ width: '100%',
41
+ height: '100%',
42
+ pointerEvents: 'none',
43
+ zIndex: String(CANVAS_Z_INDEX),
44
+ });
45
+
46
+ return canvas;
47
+ };
48
+
49
+ /**
50
+ * Bursts a dithered field of pixel blocks, lets it fall, then cleans up after itself.
51
+ *
52
+ * Every option has a default, so `confetti()` on its own fires from the bottom corners of the
53
+ * viewport. The blocks shrink as they fall and as they fade, and the ones furthest back start
54
+ * smaller, which is what gives the field its depth.
55
+ *
56
+ * Only one burst runs at a time: a call made while another is still on screen does nothing and
57
+ * returns a no-op, so a double click cannot stack two canvases.
58
+ *
59
+ * Does nothing when the user prefers reduced motion, or outside a browser.
60
+ *
61
+ * The canvas is `aria-hidden`, so nobody using a screen reader will know it fired. When the
62
+ * confetti is the only sign that something worked, the caller has to convey that success in the
63
+ * accessibility tree as well.
64
+ *
65
+ * @param {Object} [options]
66
+ * @param {Number} [options.count] Number of pieces. Defaults to a count scaled to the area it
67
+ * plays in, so a small `boundary` gets proportionally fewer.
68
+ * @param {Number} [options.duration=3000] How long the animation runs, in milliseconds.
69
+ * @param {String[]} [options.colors] CSS colors for the coverage ramp, sparse to dense: the first
70
+ * paints the thinnest edge of a cluster and the last its densest center. Any length works, and the
71
+ * first four double as the chromatic fringe colors. Defaults to the brand purple, red and orange
72
+ * color tokens.
73
+ * @param {Element} [options.origin] Element to burst from. Defaults to the bottom corners.
74
+ * @param {Element} [options.boundary] Element to confine the confetti to. Defaults to the viewport.
75
+ * @example
76
+ * const stop = confetti({ origin: button, colors: ['#7759c2', '#a989f5', '#fca326'] });
77
+ * @returns {Function} Stops the animation and removes the canvas early.
78
+ */
79
+ export const confetti = ({ count, duration = DEFAULT_DURATION, colors, origin, boundary } = {}) => {
80
+ if (
81
+ typeof window === 'undefined' ||
82
+ window.matchMedia?.('(prefers-reduced-motion: reduce)').matches ||
83
+ document.querySelector(`[${RUNNING_ATTRIBUTE}]`)
84
+ ) {
85
+ return noop;
86
+ }
87
+
88
+ const canvas = createCanvas();
89
+ const context = canvas.getContext('2d');
90
+
91
+ if (!context) {
92
+ return noop;
93
+ }
94
+
95
+ const stage = measureStage(boundary);
96
+
97
+ const resize = () => {
98
+ const ratio = window.devicePixelRatio || 1;
99
+
100
+ canvas.width = window.innerWidth * ratio;
101
+ canvas.height = window.innerHeight * ratio;
102
+ context.setTransform(ratio, 0, 0, ratio, 0, 0);
103
+ };
104
+
105
+ const fadeOutDuration = Math.min(FADE_OUT_DURATION, duration);
106
+ const field = createField({ ramp: colors?.length ? colors : COVERAGE_RAMP, duration });
107
+ const cleared = { x: 0, y: 0, width: 0, height: 0 };
108
+
109
+ let lastColor = null;
110
+
111
+ const drawBlock = ({ x, y, size, color }) => {
112
+ if (color !== lastColor) {
113
+ lastColor = color;
114
+ context.fillStyle = color;
115
+ }
116
+
117
+ context.fillRect(x, y, size, size);
118
+ };
119
+
120
+ const clearStage = () => {
121
+ const moved =
122
+ stage.x !== cleared.x ||
123
+ stage.y !== cleared.y ||
124
+ stage.width !== cleared.width ||
125
+ stage.height !== cleared.height;
126
+
127
+ if (moved) {
128
+ context.clearRect(0, 0, window.innerWidth, window.innerHeight);
129
+ Object.assign(cleared, stage);
130
+ } else {
131
+ context.clearRect(stage.x, stage.y, stage.width, stage.height);
132
+ }
133
+ };
134
+
135
+ let pieces = createPieces({ stage, origin: stagePoint(origin, stage), count });
136
+
137
+ let frame = null;
138
+ let startedAt = null;
139
+ let previousAt = null;
140
+
141
+ const stop = () => {
142
+ if (frame !== null) {
143
+ window.cancelAnimationFrame(frame);
144
+ frame = null;
145
+ }
146
+ window.removeEventListener('resize', resize);
147
+ canvas.remove();
148
+ };
149
+
150
+ const render = (now) => {
151
+ startedAt ??= now;
152
+ const elapsed = now - startedAt;
153
+ const delta = Math.min(now - (previousAt ?? now), MAX_FRAME_DELTA);
154
+ previousAt = now;
155
+
156
+ if (elapsed >= duration) {
157
+ stop();
158
+ return;
159
+ }
160
+
161
+ Object.assign(stage, measureStage(boundary));
162
+ clearStage();
163
+ lastColor = null;
164
+ context.globalAlpha = Math.min(1, (duration - elapsed) / fadeOutDuration);
165
+ context.save();
166
+ context.beginPath();
167
+ context.rect(stage.x, stage.y, stage.width, stage.height);
168
+ context.clip();
169
+ context.translate(stage.x, stage.y);
170
+
171
+ pieces = pieces.map((piece) => advancePiece(piece, { elapsed, delta }));
172
+ field.resize(stage);
173
+ pieces.forEach((piece) => {
174
+ if (elapsed >= piece.delay) {
175
+ field.stamp(piece, elapsed);
176
+ }
177
+ });
178
+ field.paint(drawBlock);
179
+
180
+ context.restore();
181
+
182
+ frame = window.requestAnimationFrame(render);
183
+ };
184
+
185
+ resize();
186
+ window.addEventListener('resize', resize);
187
+ document.body.append(canvas);
188
+ frame = window.requestAnimationFrame(render);
189
+
190
+ return stop;
191
+ };