` element is somewhat redundant in these examples, but there would need to be some kind of wrapper as the complexity grows.
90 |
91 | The wrapper `
` will receive any extra attributes specified on the parent, inherited via `$attrs`. This may be desirable in some cases, such as `class`, but it also means that attributes such as `disabled` and `indeterminate` cannot be applied to the `
`. The target element for the `$attrs` can be changed using `inheritAttrs`, but either way some attributes will need to be extracted as props to ensure they are applied to the other element.
92 |
93 | ## Related Components
94 |
95 | An individual checkbox represents a choice between two values. This is effectively the same as a [Toggle Switch](./toggle-switch) (left/right) or a Toggle Button (pressed/unpressed).
96 |
97 | Multiple checkboxes can be used to model multiple selections, often represented using an `Array` or `Set` containing the selected values. This can also be represented using a list, like a `
`. Some dropdowns also support multiple selections, often in combination with a tag/chip/pill component to show the selected values when the list is collapsed.
98 |
99 | ## Libraries
100 |
101 | Various libraries include a checkbox component, including:
102 |
103 | - Vuetify - [Checkbox](https://next.vuetifyjs.com/en/components/checkboxes/)
104 | - Element Plus - [Checkbox](https://element-plus.org/en-US/component/checkbox.html)
105 | - Quasar - [Checkbox](https://quasar.dev/vue-components/checkbox)
106 | - Ant Design Vue - [Checkbox](https://www.antdv.com/components/checkbox)
107 | - PrimeVue - [Checkbox](https://primefaces.org/primevue/checkbox)
108 | - Naive UI - [Checkbox](https://www.naiveui.com/en-US/os-theme/components/checkbox)
109 | - Oruga - [Checkbox](https://oruga.io/components/Checkbox.html)
110 |
111 | Proxying `v-model` using a `computed` is so common that it features in libraries of composables:
112 |
113 | - [VueUse - useVModel](https://vueuse.org/core/useVModel/)
114 | - [vue-composable - useVModel](https://pikax.me/vue-composable/composable/misc/vmodel.html)
115 |
--------------------------------------------------------------------------------
/docs/components/checkbox/checkbox-without-input.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
21 |
22 |
41 |
--------------------------------------------------------------------------------
/docs/components/checkbox/checkbox.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
28 |
--------------------------------------------------------------------------------
/docs/components/radio-group.md:
--------------------------------------------------------------------------------
1 |
9 | # Radio Group
10 |
11 | :::info
12 | This page has not yet been updated to use the `defineModel` macro, which was added in Vue 3.4. The techniques described here should still work, but in some cases it might be better to use `defineModel` instead.
13 | :::
14 |
15 | ## Radio Group Example
16 |
17 | A radio group component acts as a wrapper around multiple radio components, with a single `v-model` on the wrapper:
18 |
19 | ```vue
20 |
21 |
22 |
23 |
24 |
25 |
26 | Bound value: {{ radioValue }}
27 |
28 |
29 |
36 | ```
37 |
38 | It would look something like this:
39 |
40 |
41 |
42 |
43 |
44 | Bound value: {{ radioValue }}
45 |
46 |
47 | [SFC Playground](https://play.vuejs.org/#eNqVU8tOwzAQ/JVVLglS2tyjUIlKwAkJAeJCOJR4W4wa2zh2JFTl31nbaaI+aMslkdezs7MzySa6UWraWozyqGgqzZWBBo1Vs1LwWkltYAMal9DBUssaYoLGw9V80fDqacG47G+n2VhyrMeg91padQTv631TKSopGgPaXbwu1hbh2slI4juuGxNflaLIglwSSgeDtVovDNIJoPhwpBPfPFn5ce2klgzX12U0UpaRR+/ioXVXhPODygiyU6BnJJ3sHOrlk+sRVGQH8kJdaZzNpRUsNOawIetHA7quyBzErT6sG6XRruOncuTiCyuzF+XWaqWlashlhksu8NGdko3TtRUTFtT4bblGloPRZCHVulJ0lMdOZA/ObCILE5N4LJ6LjvF2ayUXyhowP8p56BnIw70gPSeV863X/t0nW2SB7S+/hi/ulGmVrEkGstQ51HJGQfzPP6/XR3i5iVhzM3Dd0qFJ3mKrGK2Qj3zxu2/pde24nA66g4gVGkiuxvnGahEkT0c+LyR1T3IBEm/l0OMkJUc0pOEDISX9FpcH3KylGX6Kw6i6X+0EmxM=)
48 |
49 | `radio-group.vue` would use `provide` to communicate with `radio.vue`:
50 |
51 | <<< @/components/radio-group/radio-group.vue
52 |
53 | The `radio.vue` here is specially written to use `inject` instead of a `modelValue`:
54 |
55 | <<< @/components/radio-group/radio.vue
56 |
57 | Support for direct use of `v-model` with the `radio` component has been omitted from this example. That technique is shown in the [Radio example](./radio). The two can be combined by using a default value with `inject` and then checking whether that value is set.
58 |
59 | ## Vue Patterns
60 |
61 | See [Coupled Components with `provide`/`inject`](../patterns/coupled-components-with-provide-inject)
62 |
63 | Apart from the naming choices, there's nothing in this `radio-group.vue` implementation that assumes the children are radio buttons. It could be made to work with checkboxes, toggle switches or any similar components that involve picking from a list of options.
64 |
65 | It could be argued that injecting a `computed` like this is violating one-way data flow for updates, or at least it gives that impression from the perspective of `radio.vue`. You could inject a separate `ref` and update function if you prefer.
66 |
67 |
72 |
73 | ## Alternatives
74 |
75 | Another way to implement a radio group would be to use a prop to pass the options rather than a slot. e.g.:
76 |
77 | ```vue
78 |
79 |
83 |
84 | ```
85 |
86 | As the radio group is now responsible for creating the child components, it can use props and events for communicating with the children rather than `provide`/`inject`. This does simplify the implementation of the children, but it also forces the radio group to take on responsibility for laying out the radios. Whereas a slot allows other containers, dividers and text to be included along with the radios, the prop-based approach needs everything to be passed in via props. The slot-based approach could be seen as a better separation of concerns, though if you don't need the extra flexibility it may be unnecessary complexity.
87 |
88 | Both approaches could be implemented in the same component.
89 |
90 | ## Libraries
91 |
92 | Various libraries include a radio component, including:
93 |
94 | - Vuetify - [Radio Group](https://next.vuetifyjs.com/en/components/radio-buttons/)
95 | - Element Plus - [Radio Group](https://element-plus.org/en-US/component/radio.html)
96 | - Quasar - [Option Group](https://quasar.dev/vue-components/option-group) (uses a prop-based approach for the options)
97 | - Ant Design Vue - [Radio Group](https://www.antdv.com/components/radio)
98 | - Headless UI - [Radio Group](https://headlessui.dev/vue/radio-group)
99 | - Naive UI - [Radio Group](https://www.naiveui.com/en-US/os-theme/components/radio)
100 |
101 |
--------------------------------------------------------------------------------
/docs/components/radio-group/radio-group.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
27 |
--------------------------------------------------------------------------------
/docs/components/radio-group/radio.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
18 |
--------------------------------------------------------------------------------
/docs/components/radio.md:
--------------------------------------------------------------------------------
1 | ---
2 | outline: 'deep'
3 | ---
4 |
12 | # Radio
13 |
14 | :::info
15 | This page has not yet been updated to use the `defineModel` macro, which was added in Vue 3.4. The techniques described here should still work, but in some cases it might be better to use `defineModel` instead.
16 | :::
17 |
18 | ## Radio Examples
19 |
20 | We're going to look at two examples of a radio component. The first example wraps a native ` ` element to create the radio button. The second example uses CSS to give the impression of a radio button without using an ` `.
21 |
22 | In both cases the example usage is much the same:
23 |
24 | ```vue
25 |
26 |
27 |
28 |
29 | Bound value: {{ radioValue }}
30 |
31 |
32 |
38 | ```
39 |
40 | ### Radio with ` `
41 |
42 |
43 |
44 |
45 |
46 | Bound value: {{ radioValue }}
47 |
48 |
49 | [SFC Playground](https://play.vuejs.org/#eNqdUk1PwzAM/StWLi3Stt6rbhJDcENCgLhQDqXxWMSahDQpQlX/O05KP4ZgElyS2LGf37PdsnOtV41DlrKsLo3QFmq0Tm9yKSqtjIUWDO6gg51RFUQUGo1f26IW5W3Bhfr6XSWTy6NSaC5LJWsLxvseioNDWHvEOLoSprbRWS6zpK9MNcmwWOlDYZEsgOzZ4y1DMjTLSnE8rHM2geUMGn+TM+CRnfw58w6JI/9X6v1emFmmNrjZKid5H5BCS+2blHddlvgQr3nUyRbsuGunZlGqSjuL/NtAhi5ro3RNDea4ExJvvBW3nlkQEUgQJ+8AGsKbEwZ5CtaQJvJ1C38OzH+NymVHUxtKYiXsWPGSjDp+jJzmJC2dqkZPs5TQkWv/R4mDop7nC1qIz6bi1hnZq1pNYBNX6g/EEt8v9li+Ih8TPan4BxYLmAXPxJxaQS6a8KCnkEQV7If2ow8q/Cocb0jQRe50WJFw56wHS3q0+fi7T5caOVQ=)
50 |
51 | <<< @/components/radio/radio.vue
52 |
53 | ### Radio without ` `
54 |
55 |
56 |
57 |
58 |
59 | Bound value: {{ radioValue }}
60 |
61 |
62 | [SFC Playground](https://play.vuejs.org/#eNqdUs2O0zAQfpUhe0gq9Q8kEDVNBSvBGQHiQjik9rS1msTGdkqXKu/OOE6a7GpZib20mfHM9zMzl+iD1vNTjRGL1pYbqR1YdLXeZJUstTIOLmBwBw3sjCohptL4+nSbW8m/5EKq7nW+GFIelUqziqvKOjA+9z0vaoTUIybxJ2msiydZtV4EZuKkwGGpi9whRQDrrcebtc1wmpVKYJFm0QCWRXDy/5Rs8She/HfnVySN4lmt3w7SjDq1wc2tqisRChhcaHyD86ZZL3yJ93z1GU2j+1N7ahdclbp2KB4spJ+yNkpbGrDAnazws4+Si1fWmmhFkCafAFrCr1oaFAycIU+Ua6b+t1f+z6qsamhrPSWW0l0ZP1Jgkx9xrQVZYwNr/HPUwg/Ij+QhvdpJkgmkmyB/3gqANE27eEAZYVgskHvi0NmqlTtIXnTgAWXS2/Aqk0dkTcecBB/sPX2TQp7aj/AJvMitpVPYqjMdAutD2lVns6H0e15IfqR00D1czCKgje6hZbTurkCwXGkUlJkTeLCyVUagYfBSn8GqQgq4Wa1W74an9m5ry+CtPnfp88zKP7Las76EUu3TAeX+4AjsTVf7Wwp3uMY0B6LubDC2xZ0y2MnI+XFv/KUzuFku+WMCXnegtDCHFdHEcRsLacnpHakpFD/eF7Lsesrc7GXF4NUDYeE9LMiPaBM1fwGqtaOz)
63 |
64 | <<< @/components/radio/radio-without-input.vue
65 |
66 |
73 |
74 | ## Libraries
75 |
76 | Various libraries include a radio component, including:
77 |
78 | - Vuetify - [Radio](https://next.vuetifyjs.com/en/components/radio-buttons/)
79 | - Element Plus - [Radio](https://element-plus.org/en-US/component/radio.html)
80 | - Quasar - [Radio](https://quasar.dev/vue-components/radio)
81 | - Ant Design Vue - [Radio](https://www.antdv.com/components/radio)
82 | - PrimeVue - [RadioButton](https://primefaces.org/primevue/radiobutton)
83 | - Naive UI - [Radio](https://www.naiveui.com/en-US/os-theme/components/radio)
84 | - Oruga - [Radio](https://oruga.io/components/Radio.html)
85 |
--------------------------------------------------------------------------------
/docs/components/radio/radio-without-input.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
29 |
30 |
48 |
--------------------------------------------------------------------------------
/docs/components/radio/radio.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
30 |
--------------------------------------------------------------------------------
/docs/components/tabs.md:
--------------------------------------------------------------------------------
1 |
4 | # Tabs
5 |
6 | :::info
7 | This page has not yet been updated to use the `defineModel` macro, which was added in Vue 3.4. The techniques described here should still work, but in some cases it might be better to use `defineModel` instead.
8 | :::
9 |
10 | ## Tabs Example
11 |
12 | There are various ways to split a tabbed UI up into components. In this example we're going to use two components, an outer container called `tabs` and an inner container for each child called `tab`:
13 |
14 | <<< @/components/tabs/example.vue
15 |
16 |
17 |
18 |
19 |
20 | [SFC Playground](https://play.vuejs.org/#eNqNVstu2zoQ/ZWpurACSLZ7cW8K6NpB20W3LfpY1V3IImWzlUiWpNwEhv+9w4doKnGaGJAtcs7MnHlw6GP2Vsr5YaBZla10o5g0oKkZ5M2Gs14KZeBdrVnzpd5qaJXoYTZfxB2rOHsAfIALsNXCO0DTuDC0l11tKK4AVlsLLQ3adOt0BwwzHV1vsvdMabPJAgDArcEiGsEN5SZoLqLq47Y+U9QhibHIBw5lKxRCGDAO/ywTDIBXS33C8QgMTqczZrVVaIO1zsSL9XpqY7WYBP5Mul/2TKVs3frp0JO1zWviOyuySRUfL/8RXfRyMJQUIJU4MEILULRuDDu4txZOoeK+zBuOnLAwHgFrC8n50HVXo8TScfsekn/7jqKJmq3D2sW3voGjDcVD54e6G4JowzHpGx445TNrtVR0x7ShalZMtK1sLge9z/HNOQNgLeQvUrNXHht8IYUABnCOAAmbQfEJilYxPXl+Zf1NiWL5rZHCGwAY+MgQEB4sga0ihs44obc+OD13iw9t5GA/TqBlxxqaO3kBr0I09mMjuuj+7GganP62tKn3gtDC7ge/Tij424kl7ABNV2uN7WlNxe6cSPa0JlSl/b8djBGRMsTjZsuFB86bOosTF2VQTaTVKD7GcriyY9yh/U4p/E2DqfuJ8GmFI+IGDzPuzN2xw0ON58e5jEcVQ7sU5VaQuzRG3QkDiwda49tkBuBSmzt0pxshKcGduTsfrmRboTB9FbySt6BFxwi8bJrmfysiDBuhvqug7eit27EvJWGKYnCC28bshp470Z6y3d5UOIqW0oN/M2L2FfwbNlyHz321guu6+blTYuCkREMCSbyk1+112zp1T6zcCkxP/0x+siaE8R2yQLR9ltHxubr3naPbduLzorN7dKzhuKlqwgZdwX+oZp9lEDeD0jYsKRiOUOX2+lrtGC9VyFbIVY9bIV+vx/zFYNDkhTCqvTj8JZPt67ZxUXm90KtPoiPBMdASc5HSiYLrhJXtzufYvtxRmO+nusuG2nbidwX1YIT3i6PDdnV60Tx1zzD+A40XIPhX3iNJd+WcbxojPj161+AlIO2VQmjLOP1oV7kf/PYkV+P8U/TXgBFgUxk1UBzKbqjeSUR8Ngrzl8y+0XSc1+tA8P5Nk2Dd7DnfaykDxz53PAuYuU2rmXoaZ1iR3hInZ9Av4uWVZCg/Y58xsMP/Eu9nk6XT9Ty/k+l1cWJlpz/lxGh7)
21 |
22 | The `title` prop is used to pass the text to show on the button, with a slot for the content.
23 |
24 | The code for `tabs.vue` looks long, but a lot of it is CSS:
25 |
26 | <<< @/components/tabs/tabs.vue
27 |
28 | `tab.vue` doesn't need much code:
29 |
30 | <<< @/components/tabs/tab.vue
31 |
32 | ## Vue Patterns
33 |
34 | See [Coupled Components with `provide`/`inject`](../patterns/coupled-components-with-provide-inject)
35 |
36 |
41 |
42 | ## Libraries
43 |
44 | Various libraries include a tabs component, including:
45 |
46 | - Vuetify - [Tabs](https://next.vuetifyjs.com/en/components/tabs/)
47 | - Element Plus - [Tabs](https://element-plus.org/en-US/component/tabs.html)
48 | - Quasar - [Tabs](https://quasar.dev/vue-components/tabs) and [Tab Panels](https://quasar.dev/vue-components/tab-panels)
49 | - Ant Design Vue - [Tabs](https://www.antdv.com/components/tabs)
50 | - Headless UI - [Tabs](https://headlessui.dev/vue/tabs)
51 | - PrimeVue - [TabView](https://primefaces.org/primevue/tabview)
52 | - Naive UI - [Tabs](https://www.naiveui.com/en-US/os-theme/components/tabs)
53 | - Oruga - [Tabs](https://oruga.io/components/Tabs.html)
54 |
--------------------------------------------------------------------------------
/docs/components/tabs/example.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | First tab content
5 |
6 |
7 |
8 | Second tab content {{ i }}
9 |
10 |
11 |
12 |
13 | Third tab content
14 |
15 |
16 |
17 |
18 |
22 |
--------------------------------------------------------------------------------
/docs/components/tabs/tab.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
27 |
--------------------------------------------------------------------------------
/docs/components/tabs/tabs.vue:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
18 |
49 |
50 |
95 |
--------------------------------------------------------------------------------
/docs/components/toggle-switch.md:
--------------------------------------------------------------------------------
1 |
7 | # Toggle Switch
8 |
9 | :::info
10 | This page has not yet been updated to use the `defineModel` macro, which was added in Vue 3.4. The techniques described here should still work, but in some cases it might be better to use `defineModel` instead.
11 | :::
12 |
13 | ## Toggle Switch Example
14 |
15 | Using a toggle switch should be very similar to using a checkbox:
16 |
17 | ```vue
18 |
19 |
20 | Bound value: {{ switchValue }}
21 |
22 |
28 | ```
29 |
30 | `v-model` is used to achieve a two-way data binding on the data value held in the parent.
31 |
32 |
33 |
34 | Bound value: {{ switchValue }}
35 |
36 |
37 | [SFC Playground](https://play.vuejs.org/#eNq9VE2P2jAQ/SvT9LAgkQC72rZKWdSu1HulVr2UHoztEAvHdm0HukL8945tCJ/bSq20EgI8M543771JNtlHY4pVy7MymzhqhfHguG/NdKZEY7T1sAHLK9hCZXUDN1h606UeiRP0q14sJP+yFp7Wu6JieJEJGHhxpqhWDjFi8BuRLYeHANDztuX9mZoM0xSIjwfPGyOJ53gCmMxD09zHrnnqAKu80YzLh1l21HKWwTBdMZZPH3WrGKxCooTN5gR7u50MQ00A7sCyQXZ1/isaJTbGauOQB+OVUPxzOPU2AT/OFpEQOQQAuf5sheWshMB4kIL+yWDFo9aSE+QNsJ2pLaqxB+CN8F3/T3hwve83rWE4bXnAuPlxdCXJhJd6fXiYJvTQpnfl3gBeRQrFIYadcIY/ucHEKg1PJXEODTgxZpalZLnPboDWnC4D8QMK8tzVfaBS0GXXJYWDiUe+xCGcf0JajmrDGUaK03WINOeELhc2uF7Ca8bY+xjUlnGbW8JE60oYFW/vebPL/MpdTZheh/DozS0mrvyxiznpjQaw+xSjd30QChchNqGtddqWYLRQntsYqyT/VYLSisdjzcWi9iWMiz2y0U54oVWJW4EMxSoVekvUPnHgklMttYXx/ahxsWwtmK9LuIvN0KxzMcpyzitt+RVRqqpK1A/dRUMWuINBHyLzRfjlyveosBT1Jh4Z3wXJ9r+Dc0H64ftCpPs+jHnTv25BFPY/PUjqaxRdoba4N1mMMOFwaZ5QQKnp8kz/DlbyCgOjYtxFDpaQudOy9TtLtDmtO/YodLn05QhmLaTMaU1UUDhUd4btnolzi5LXaBQh9K66PS9/ztmXMDFJNu68u7Z4tV5xuxvuL8ZGRS8Qx7eHZ+tZgJdWAWtPlvmfNhaZJU74ag1vsmm2/Q3F9nG4)
38 |
39 | The implementation includes a lot of CSS, but it is otherwise very similar to a checkbox:
40 |
41 | <<< @/components/toggle-switch/toggle-switch.vue
42 |
43 |
48 |
49 | ## Related Components
50 |
51 | An individual toggle switch represents a choice between two values. This is effectively the same as a [Checkbox](./checkbox) (checked/unchecked) or a Toggle Button (pressed/unpressed).
52 |
53 | Multiple toggle switches can be used to model multiple selections, often represented using an `Array` or `Set` containing the selected values. This can also be represented using a list, like a ``. Some dropdowns also support multiple selections, often in combination with a tag/chip/pill component to show the selected values when the list is collapsed.
54 |
55 | ## Libraries
56 |
57 | Various libraries include a toggle switch component, including:
58 |
59 | - Vuetify - [Switch](https://next.vuetifyjs.com/en/components/switches/)
60 | - Element Plus - [Switch](https://element-plus.org/en-US/component/switch.html)
61 | - Quasar - [Toggle](https://quasar.dev/vue-components/toggle)
62 | - Ant Design Vue - [Switch](https://www.antdv.com/components/switch)
63 | - Headless UI - [Switch](https://headlessui.dev/vue/switch)
64 | - PrimeVue - [InputSwitch](https://primefaces.org/primevue/inputswitch)
65 | - Naive UI - [Switch](https://www.naiveui.com/en-US/os-theme/components/switch)
66 | - Oruga - [Switch](https://oruga.io/components/Switch.html)
67 |
--------------------------------------------------------------------------------
/docs/components/toggle-switch/toggle-switch.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
23 |
24 |
71 |
--------------------------------------------------------------------------------
/docs/exercises/abbey-road.js:
--------------------------------------------------------------------------------
1 | const tracks = [
2 | 'Come Together',
3 | 'Something',
4 | 'Maxwell\'s Silver Hammer',
5 | 'Oh! Darling',
6 | 'Octopus\'s Garden',
7 | 'I Want You (She\'s So Heavy)',
8 | 'Here Comes The Sun',
9 | 'Because',
10 | 'You Never Give Me Your Money',
11 | 'Sun King',
12 | 'Mean Mr Mustard',
13 | 'Polythene Pam',
14 | 'She Came In Through The Bathroom Window',
15 | 'Golden Slumbers',
16 | 'Carry That Weight',
17 | 'The End',
18 | 'Her Majesty'
19 | ]
20 |
21 | const mappings = {
22 | 'octopus garden': 'octopuss garden',
23 | 'octopuses garden': 'octopuss garden',
24 | 'i want you': 'i want you shes so heavy',
25 | 'shes so heavy': 'i want you shes so heavy',
26 | 'mean mister mustard': 'mean mr mustard',
27 | }
28 |
29 | function canonical(str) {
30 | const replaced = str.toLowerCase().replace(/[^a-z ]/g, '').replace(/ +/, ' ').trim()
31 |
32 | return mappings[replaced] || replaced
33 | }
34 |
35 | const canon = tracks.map(canonical)
36 |
37 | export default {
38 | question: `Name the ${tracks.length} tracks on The Beatles album Abbey Road`,
39 | size: tracks.length,
40 |
41 | createChecker() {
42 | return (answer) => {
43 | const index = canon.indexOf(canonical(answer))
44 |
45 | if (index === -1) {
46 | return false
47 | }
48 |
49 | return {
50 | index,
51 | canonical: tracks[index]
52 | }
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/docs/exercises/elements.js:
--------------------------------------------------------------------------------
1 | const elements = [
2 | 'Actinium',
3 | 'Aluminium',
4 | 'Aluminum',
5 | 'Americium',
6 | 'Antimony',
7 | 'Argon',
8 | 'Arsenic',
9 | 'Astatine',
10 | 'Barium',
11 | 'Berkelium',
12 | 'Beryllium',
13 | 'Bismuth',
14 | 'Bohrium',
15 | 'Boron',
16 | 'Bromine',
17 | 'Cadmium',
18 | 'Caesium',
19 | 'Calcium',
20 | 'Californium',
21 | 'Carbon',
22 | 'Cerium',
23 | 'Chlorine',
24 | 'Chromium',
25 | 'Cobalt',
26 | 'Copernicium',
27 | 'Copper',
28 | 'Curium',
29 | 'Darmstadtium',
30 | 'Dubnium',
31 | 'Dysprosium',
32 | 'Einsteinium',
33 | 'Erbium',
34 | 'Europium',
35 | 'Fermium',
36 | 'Flerovium',
37 | 'Fluorine',
38 | 'Francium',
39 | 'Gadolinium',
40 | 'Gallium',
41 | 'Germanium',
42 | 'Gold',
43 | 'Hafnium',
44 | 'Hassium',
45 | 'Helium',
46 | 'Holmium',
47 | 'Hydrogen',
48 | 'Indium',
49 | 'Iodine',
50 | 'Iridium',
51 | 'Iron',
52 | 'Krypton',
53 | 'Lanthanum',
54 | 'Lawrencium',
55 | 'Lead',
56 | 'Lithium',
57 | 'Livermorium',
58 | 'Lutetium',
59 | 'Magnesium',
60 | 'Manganese',
61 | 'Meitnerium',
62 | 'Mendelevium',
63 | 'Mercury',
64 | 'Molybdenum',
65 | 'Moscovium',
66 | 'Neodymium',
67 | 'Neon',
68 | 'Neptunium',
69 | 'Nickel',
70 | 'Nihonium',
71 | 'Niobium',
72 | 'Nitrogen',
73 | 'Nobelium',
74 | 'Oganesson',
75 | 'Osmium',
76 | 'Oxygen',
77 | 'Palladium',
78 | 'Phosphorus',
79 | 'Platinum',
80 | 'Plutonium',
81 | 'Polonium',
82 | 'Potassium',
83 | 'Praseodymium',
84 | 'Promethium',
85 | 'Protactinium',
86 | 'Radium',
87 | 'Radon',
88 | 'Rhenium',
89 | 'Rhodium',
90 | 'Roentgenium',
91 | 'Rubidium',
92 | 'Ruthenium',
93 | 'Rutherfordium',
94 | 'Samarium',
95 | 'Scandium',
96 | 'Seaborgium',
97 | 'Selenium',
98 | 'Silicon',
99 | 'Silver',
100 | 'Sodium',
101 | 'Strontium',
102 | 'Sulfur',
103 | 'Sulphur',
104 | 'Tantalum',
105 | 'Technetium',
106 | 'Tellurium',
107 | 'Tennessine',
108 | 'Terbium',
109 | 'Thallium',
110 | 'Thorium',
111 | 'Thulium',
112 | 'Tin',
113 | 'Titanium',
114 | 'Tungsten',
115 | 'Uranium',
116 | 'Vanadium',
117 | 'Xenon',
118 | 'Ytterbium',
119 | 'Yttrium',
120 | 'Zinc',
121 | 'Zirconium'
122 | ]
123 |
124 | const lastLetters = [...new Set(elements.map(el => el.slice(-1)))].sort()
125 |
126 | export default {
127 | question: `Name ${lastLetters.length} chemical elements with different last letters`,
128 | size: lastLetters.length,
129 |
130 | createChecker() {
131 | const usedLetters = new Set()
132 | let index = 0
133 |
134 | return (answer) => {
135 | const canonical = answer.slice(0, 1).toUpperCase() + answer.slice(1).toLowerCase()
136 |
137 | if (elements.includes(canonical) && !usedLetters.has(canonical.slice(-1))) {
138 | usedLetters.add(canonical.slice(-1))
139 |
140 | return {
141 | canonical,
142 | index: index++
143 | }
144 | }
145 |
146 | return false
147 | }
148 | }
149 | }
150 |
--------------------------------------------------------------------------------
/docs/exercises/index.md:
--------------------------------------------------------------------------------
1 |
7 |
8 | # Exercises
9 |
10 | * [Tic-tac-toe](./tic-tac-toe)
11 | * [Quiz](./quiz)
12 | * [Minesweeper](./minesweeper)
13 | * [Numbers Game](./numbers-game)
14 |
15 | These exercises are intended for programmers new to Vue to practice their skills. You should read through the [official Vue documentation](https://vuejs.org/) first. Keep the documentation open while working on these exercises, as you'll likely need to look things up as you go.
16 |
17 | The exercises don't have exact requirements. You can choose how far you want to take a particular exercise and what features to add.
18 |
19 | No scaffolding or boilerplate code is provided to help you out. Each exercise is a self-contained project, and you have to create it from scratch. If you're new to web development, or programming in general, you may find these exercises too difficult. But that doesn't mean you shouldn't give them a go.
20 |
21 | It is possible to attempt the exercises directly in the [SFC Playground](https://play.vuejs.org/). However, if you're new to Vue then you'd be better off using a proper IDE to help you avoid basic errors. Using `npm init vue@latest` to create a starter project should work well for the exercises given here.
22 |
23 | Each exercise includes a reference solution, but you should attempt to write your own version before consulting the example code. You won't get as much out of it if you haven't tried it for yourself.
24 |
25 | If you'd rather just look at some examples, take a look at the [official examples](https://vuejs.org/examples/) instead, and save these exercises for another time.
26 |
27 | If a particular exercise feels too difficult, try breaking it down into smaller steps. Implement one small part of it. You don't need to have the entire application mapped out in your head before you start, you can move incrementally towards it and rewrite sections of the code as you improve your understanding of the problem.
28 |
--------------------------------------------------------------------------------
/docs/exercises/minesweeper.md:
--------------------------------------------------------------------------------
1 |
4 |
5 | # Minesweeper
6 |
7 | The classic computer game.
8 |
9 | Players begin with a rectangular grid of buttons. Clicking a button reveals what is lurking behind.
10 |
11 | Behind some of the buttons are mines (bombs). The player loses if they click on a mine.
12 |
13 | Behind the other buttons are numbers, indicating how many mines are adjacent to that button. Diagonals are included, so central squares have 8 adjacent squares, whereas corner squares have just 3.
14 |
15 | If a square has no adjacent mines, the square is shown as empty, rather than 0. When such a square is revealed, all adjacent squares will also be revealed. This saves the player from having to click the buttons for squares that they already know are not mines.
16 |
17 | Players can also place flags on buttons by right-clicking (ctrl+click on Mac). Flags help the player to keep track of where mines are located. If a flag is placed incorrectly, it must be removed before the square can be revealed.
18 |
19 | The player wins by revealing all of the squares that do not contain mines.
20 |
21 | The game should be implemented to ensure that a player's first click will never reveal a mine.
22 |
23 | ## Example
24 |
25 |
26 |
27 |
28 |
29 | View it on the [SFC Playground](https://play.vuejs.org/#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)
30 |
31 | ## Features Used
32 |
33 | Your implementation doesn't need to use the same Vue features as the example above, but to give you some idea of the knowledge you might need to attempt this:
34 |
35 | * The example above is written using a single component.
36 | * It uses a Single-File Component with `
151 |
152 |
153 |
154 | Flagged {{ flagged }} / {{ MINES }} mines
155 |
156 |
157 |
158 |
159 |
160 | {{ cell.value === true ? '💣' : cell.value || '' }}
161 |
162 |
168 |
169 |
170 |
171 |
172 | Game over, you {{ shake ? 'lose' : 'win' }}!
173 |
174 |
175 |
176 |
317 |
--------------------------------------------------------------------------------
/docs/exercises/numbers-game.md:
--------------------------------------------------------------------------------
1 |
4 |
5 | # Numbers Game
6 |
7 | This game is based on the 'numbers game' from the British game show [Countdown](https://en.wikipedia.org/wiki/Countdown_(game_show)), which is itself based on the French TV show [Des chiffres et des lettres](https://en.wikipedia.org/wiki/Des_chiffres_et_des_lettres).
8 |
9 | The rules of the game are mostly quite intuitive, but explaining them in detail makes it seem a lot more complicated than it actually is.
10 |
11 | There is a running version of the game at the link below, which you may want to use to get more familiar with the game:
12 |
13 |
14 |
15 | A rough outline of the rules:
16 |
17 | * Players are given 6 starting numbers and a target number. The 6 starting numbers must be manipulated using basic arithmetic to try to reach the target number.
18 | * The target number is between 100 and 999 inclusive. It is chosen at random and is not necessarily achievable.
19 | * Only the operators +, -, × and ÷ may be used. An operation is only allowed if it yields a positive, integer result.
20 | * The 6 start numbers are selected from a set of 24. These consist of the four 'large numbers' 25, 50, 75 and 100, plus two copies of the 'small numbers' 1 to 10.
21 | * The player may choose how many large numbers they want, from 0 to 4.
22 | * Each of the start numbers may only be used once in the calculation. Similarly, the output of an operation may only be used once in subsequent steps.
23 | * Not all of the 6 starting numbers need to be used.
24 |
25 | Example game:
26 |
27 | ```
28 | Target: 377
29 | Start numbers: 50 8 7 7 5 3
30 |
31 | Possible solution:
32 | Step 1: 50 - 3 is 47
33 | Step 2: 47 × 8 is 376
34 | Step 3: 7 ÷ 7 is 1
35 | Step 4: 376 + 1 is 377
36 |
37 | The number 5 is not used in this solution
38 |
39 | Alternative solution:
40 | Step 1: 50 × 7 is 350
41 | Step 2: 7 × 5 is 35
42 | Step 3: 350 + 35 is 385
43 | Step 4: 385 - 8 is 377
44 |
45 | The number 3 is not used in this solution
46 | ```
47 |
48 | ## Example
49 |
50 | A basic implementation of the game might look something like this:
51 |
52 |
53 |
54 |
55 |
56 | View it on the [SFC Playground](https://play.vuejs.org/#eNqVV9tu4zYQ/ZVZP6zl2JZsA2lRJ/FuCxTtSxug6ZsVFLJE22ookpAoJ4Hhf++QFCVS1u52ESSS5nLmPmTOo5+FCE81Ga1H91Va5kJCRWQtNjHLC8FLCWdIeSFqSbIZlCRJZX4i6m0PF9iXvIAxqo9jFrOUs0oCFxU8wDlmAOPpeA1BMoPdBB42kMAUdjPNmPcYc8u46TFuLCPqMSLYxezSmaVJeSBoGB0LlpOOXsmklH/WxY6Uyi/FZjWlKGH4yD4QOcRh5E0+SSIa3njcciqkGjCTjmD7rC0aW+T1t6QggedDTulfpEhylrMDKtqMBoGOhhn3WonAdTo8JbTGjGujE426rxna5QyI4iWSPApSJoqCERTLGdZgpkBXE1MH40VJqpqqSLFCWy6eG1ktp1ABJWRdMiu4gQV8/Ah/JPIYlrxmWWAY6PKDil0LfbIva9gntCJNTVoPh0NTHjYeV56PjLxi2Cq32zAMteyz8W3PSwhshwHfXyNYjJxl5G2JEA1YqAmP+4CL7UIVSolaXiVonpLA6MxAdU4PaTWMtPoa0qpDsmxRV8fgul4YJReqqgA6cQ4eDl8Q7GaQdDPi16mR7KecM9W1vzJJSmwvJ7mqg3Qwpq9NY4UlETRBx6M4rqLDDHSfW5UikekRdZRqqD+CKIjjbDoJttM4nt/EcfQ8MZSo8S7fQ6BFe3XZ/qObbfkky65D8eMZ8bW8K6wEkT5tFHosVRPFUurGqMNsJt00kDt4JmDsp6FeaYbNVljZbeIxETWSH7D158s2MixXozjQSFak30zXpuwAesZW18auRvmbC6DDNch2hB1IMKvFdOjW17dN3sTqdQ6aH+Pet0xsQu9FP/CP35wiT18eGQmSsvR6U0eMiHrb7CnnZWAWT8IyXmAf3wCqhJSwgzz6Y6DobvZV8nHQ+5b95WxsfyEgkw9jC4kLY65tMN1dzVpyDp/ukNmubmdwu5jBj/hcLpQv7QwWCaWOpLvdKJ5DORKXd/i4x+fiDqbTvC2Wq2uqlc8gd3eHB4PaCGN8MwH6cCoSA2OL4obh7aQh3B9wIX0Htuu8v+++seyuz0IzQ7j3FNuc3y3jK/3z02KBFxAsBwKj7fvI3HfwpoMfkhS4BiXBL4D7LD9BSpOqeohHHA/qMh5pRo8luZjvko6J7EokbPM7f8WNxt6bS0kz8J/QouJ2soSSVMJpXvCMUMTT4g4aynChm/c0xxKgRKB26ASnBW7jEax11EhmnhLA+QwMLu1EIk5kgDrjkbHeEXa1lGjpc4qT9IKY7rx48EiDgyK2UEbVZijCFNn3Y+nkzYlclpwdNn/r2q3RF/Ot/G7uY9Z5D20I40m5aVPsQ3md8y/PWTDG420yjG0bAFOd73X43Q5wC1xTtzw0b0vT35yqSBpkoDbqcLtc1CveZcyLPtXwFa/O5/9xr/OLS3OnsI6HA0XVm54LvJ66bv2SpC9fqGcv713m7RYr7fnaz7539nb571z3ChB5I4iEnOEd2Yq2VfFAmxW9gaW6qX7ocXOW0jojVWB6CiPu0OzI2ROg431+Ie8Cj8kqJOoKpTZAd6GyYu42GHbt2nibQtP2+r+HI8k+9JvRvnkZwc9KvlMCVYoX3wwpoV5MZuGKJMtUAWC1EG93zcnXCGxw9U3xVwsWaDpn8x3HAhdrXOUOEbdZD6DZb0MQqKt/lq28Kj46iJ6NLv8B64OaUg==).
57 |
58 | For a much more embellished version of the game, see (as linked earlier):
59 |
60 |
61 |
62 | That version is also implemented in Vue, and its code can be seen in [its GitHub repo](https://github.com/skirtles-code/vue-numbers-game).
63 |
64 | ## Features Used
65 |
66 | It's up to you how far you want to take this exercise. The basic example above only scratches the surface, whereas the more advanced example probably goes too far. Decide for yourself when you're happy to stop adding extra functionality.
67 |
68 | For the basic implementation shown above:
69 |
70 | * It is written using a single component.
71 | * It uses a Single-File Component with `
107 |
108 |
109 |
110 |
111 | How many large numbers?
112 |
113 |
114 | {{ n }}
115 |
116 |
117 |
118 | New game
119 |
120 |
121 |
122 |
123 | Target: {{ target }}
124 |
125 |
126 | Start numbers: {{ startNumbers.join(', ') }}
127 |
128 |
129 |
130 |
131 | {{ num1 }} {{ op }} {{ num2 }} = {{ evaluateOperation(num1, op, num2) }}
132 |
133 |
134 |
135 | Back
136 |
137 |
138 | Numbers remaining: {{ stillRemaining.join(', ')}}
139 |
140 |
141 |
146 |
147 | Target reached!
148 |
149 |
150 |
151 |
152 |
166 |
--------------------------------------------------------------------------------
/docs/exercises/platonic-solids.js:
--------------------------------------------------------------------------------
1 | const solids = ['Tetrahedron', 'Cube', 'Octahedron', 'Dodecahedron', 'Icosahedron']
2 |
3 | export default {
4 | question: `Name the ${solids.length} Platonic solids`,
5 | size: solids.length,
6 |
7 | createChecker() {
8 | let index = -1
9 |
10 | return (answer) => {
11 | const canonical = answer.slice(0, 1).toUpperCase() + answer.slice(1).toLowerCase()
12 |
13 | if (!solids.includes(canonical)) {
14 | return false
15 | }
16 |
17 | ++index
18 |
19 | return {
20 | index,
21 | canonical
22 | }
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/docs/exercises/quiz-game.vue:
--------------------------------------------------------------------------------
1 |
68 |
69 |
70 |
71 | Topic:
72 |
73 | Antiquity
74 | Chemistry
75 | Geometry
76 | Music
77 |
78 |
79 |
80 | {{ question.question }}
81 |
82 |
83 |
84 |
85 | {{ matched.size }} / {{ question.size }}
86 |
87 |
88 | {{ timeTaken }}s
89 |
90 |
91 |
92 |
93 |
98 | {{ answers[index - 1] ?? '?' }}
99 |
100 |
101 |
102 |
103 | Reset
104 |
105 |
106 |
107 |
144 |
--------------------------------------------------------------------------------
/docs/exercises/quiz.md:
--------------------------------------------------------------------------------
1 |
4 |
5 | # Quiz
6 |
7 | There are lots of ways to implement a quiz.
8 |
9 | A common approach is to use multiple choice questions, allowing the player to click on the correct answers.
10 |
11 | The example shown below takes a different approach, with the player typing answers into a text input. Correct answers are shown beneath, after they are typed in.
12 |
13 | ## Example
14 |
15 |
16 |
17 |
18 |
19 | View it on the [SFC Playground](https://play.vuejs.org/#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)
20 |
21 | Some questions allow for slight variations on the answer, such as case insensitivity, ignoring punctuation, or allowing different ways to word an equivalent answer.
22 |
23 | The answers to the **Music** question are in a particular order. They don't have to be entered in that order, but matches are shown in the correct order.
24 |
25 | The answers to the **Chemistry** question are dynamic, changing based on previous answers.
26 |
27 | ## Features Used
28 |
29 | Your implementation doesn't need to use the same Vue features as the example above, but to give you some idea of the knowledge you might need to attempt this:
30 |
31 | * The example above is written using a single component, with separate `.js` data files for each question.
32 | * It uses a Single-File Component with `
4 |
5 | # Tic-tac-toe
6 |
7 | Also known as **Noughts and Crosses**, or **Xs and Os**.
8 |
9 | Players take it in turns to place their symbol in one of the grid squares. A player wins if they form a straight line of 3 in a row. Horizontal, vertical and diagonal lines all count. The game ends with no winner if all squares are filled without forming a line.
10 |
11 | ## Example
12 |
13 |
14 |
15 |
16 |
17 | View it on the [SFC Playground](https://play.vuejs.org/#eNqFVW1v2zYQ/isXb4DkNVKdxE1aLU425MMwYJiHfTJgG6giUTZbmhQoyonr+r/v+GopTroPNsl7fe7h8bQf/F7X6bYlg2xw2xSS1goaotr6bsHpphZSwR4KsalbRcpzkCQvFN0SvavgAJUUG4jQPVrwBS8EbxQ8ilyWMAm28Xw59Lqa5TsijbKKo1mECq96opxTvnogjDVo4HPG8RAmd7BfcECZM9QG82h0cRmdQ3Q1/qCX65uPehldXevlYnyjl8sPVjg2y+X4OlrqQPpXCQmxjViYnKIyoYc2l89GeUmeiUGkrdKmZlTFUTRMN3kd/91uHonEKo4OjHKC1s7PWJm9rsJQMzfH5TD9IijXkay3/acVxDbCZALRbDaL4Pt3F1NLptNpFBAC0qhayX0yKz3oxfzpn7PgLWMLfjjl+x9/I28TfqSge0fpNmct8Wk0bmcX4LnUnaJJMx8tzQ38P75VviHT7ZvQnN/Z2SkmzZhJGhhOGeErtTYUfvJpqpZjfwpuLvaB0eJrrHcOvi7IItfCpY7pEdksL8rsFdV1nLimP/LVPaM6mk2jVBKUFiTu6rBjdXO4qAGuJI3KpUIuDABbqS8QRq9mwOeJYTpBlPhTX0gsxdM58svaDXfxHLGogF/gCt45LSQwPg0ym74d4RS5JTpvGtsqztxet8fafSJwfw8R2dRqh/h77TK31H/WEZOf98Y5VeIv8UTkQ96QeHj4fG5t9rprs1da9z6lvGBtSQIcgxfbE9fb93YY4hjEg0IQLFcETwC3Jd1CocuYLAYG7mIAmRfswU69DM5CBx8WA+PpfLcJzh401RRTDlfo7r1RFGyttd9DcNM1O7+j0gfQyq484Dpy37963fHDrsdvhX4KwUM/ix96BLRI9d5d36nDEg6GXVPWe6zLExL2nZ0liVYIwnMYWPkDBSBQcuYC+LvxHr251iETwfVH3uFg5r3H0b/jl2AIa6zGBHKfMYyghDm88HlslcJ+D1S6JxvQ/OvOxssao6aHAY+N2jECTSFqUqIktR9W82bWhK7WKoOr0ah+/lVLnmip1l1BSfFTle8yqBixEr1JSiqJeY2Ze7SoMq861e1ogr/umcFFz/QdmCU17Wj8NrlcUZ4oUWeQXBoY1vxokjO64gnFOhvMT7gi0iQoWtkImUFJqrxl6gcFWBj6881V0tBv+NDGH13JX9pG0WqX4ERRGLuX4VHIkmAGxAWNYLSEn0ajUR8ilnRSDSMVBjopJ3n2w4tp3JKUfbXoqTHVp6C388GmSsx0c7aOgxo/Whb1W/bZWj8AN/7z4utKipaXmIYQEtywt1+xKKqiQwcy5fDdaCoAviVmFIa7xjGom/BucPgPtulfdQ==)
18 |
19 | ## Features Used
20 |
21 | Your implementation doesn't need to use the same Vue features as the example above, but to give you some idea of the knowledge you might need to attempt this:
22 |
23 | * The example above is written using a single component.
24 | * It uses a Single-File Component with `
63 |
64 |
65 |
75 |
76 | Game over!
77 |
78 | {{ winningPlayer }} wins
79 |
80 |
81 |
82 | {{ player }} to play
83 |
84 |
85 | Restart
86 |
87 |
88 |
89 |
151 |
--------------------------------------------------------------------------------
/docs/guides/working-with-image-assets.md:
--------------------------------------------------------------------------------
1 | ---
2 | outline: 'deep'
3 | ---
4 | # Working with Image Assets
5 |
6 | Let's imagine you have something like this in a Vue component template:
7 |
8 | ```vue-html
9 |
10 | ```
11 |
12 | It works fine. You then try to change it to something dynamic:
13 |
14 | ```vue-html
15 |
16 | ```
17 |
18 | `imgSrc` is a string containing the path from the original code, yet it doesn't work. But, why? Surely they're equivalent?
19 |
20 | Another way you might encounter the same problem is trying to pass the path to a component rather than an ` `. For example:
21 |
22 | ```vue-html
23 |
24 |
25 |
26 |
27 |
28 | ```
29 |
30 | ## Assets and Build Tools
31 |
32 | You'll encounter the same problem with both Vite and the old Vue CLI (webpack).
33 |
34 | Both tools have a convention of putting assets such as images in the folder `/src/assets`, but there's no special handling for that folder in those tools. Assets need to be imported into your JS/TS code, just like other dependencies. If they aren't imported then they'll be discarded as part of the tree-shaking process and won't be included in the final build output.
35 |
36 | As part of the build process the images will be copied and renamed. So even though you have `../assets/image.png` in your code, that isn't where the image will be in a production build. The actual path will be something like `/assets/image.12345678.png`, including a hash of the file contents for cache-busting purposes. Importing the image will yield the correct path to use at runtime.
37 |
38 | So, for example:
39 |
40 | ```vue
41 |
47 |
48 |
49 |
50 |
51 | ```
52 |
53 | If you've configured a [`base`](https://vitejs.dev/guide/build.html#public-base-path) path (Vite) or a [`publicPath`](https://cli.vuejs.org/config/#publicpath) (Vue CLI) then that will also be automatically added to the imported path string.
54 |
55 | ## Why Does a Static `src` Work?
56 |
57 | So if images need to be imported, why does ` ` work just fine?
58 |
59 | That's a special case. The build tools look for ` ` and import that path automatically. They do the same with several other native HTML elements too, and can be configured to work with custom components. The specifics depend on what tools you're using:
60 |
61 | - Vite: [@vitejs/plugin-vue](https://github.com/vitejs/vite-plugin-vue/tree/main/packages/plugin-vue#asset-url-handling)
62 | - Vue CLI / webpack: [Vue Loader](https://vue-loader.vuejs.org/guide/asset-url.html)
63 |
64 | But that can only handle static paths, hard-coded directly into the template.
65 |
66 | ## Dynamic Paths
67 |
68 | ### `import`
69 |
70 | Using an `import` statement doesn't allow for dynamic paths, but if you only have a small number of images then that's not necessarily a problem. The images can be statically imported individually, with other code to choose the appropriate image:
71 |
72 | ```vue
73 |
79 |
80 |
81 |
82 |
83 | ```
84 |
85 | ### `import()`
86 |
87 | It is theoretically possible to use the `import()` function to import an image, but that will wrap the value we need in a promise. It can be made to work, but it's fiddly:
88 |
89 | ```vue
90 |
99 |
100 |
101 |
102 |
103 | ```
104 |
105 | The advantage of `import()` is that the path can be dynamic, e.g. ``import(`../assets/${name}.png`)``. Thankfully there are other ways to achieve this that don't involve promises. With Vite we can use [`new URL()`](#new-url) or [`import.meta.glob()`](#import-meta-glob), and with Vue CLI / webpack we can use [`require()`](#require).
106 |
107 | Whichever approach we use, it's important to understand roughly how they work. All of them rely on static analysis at build time. This means that the build tool is searching through your code for one of these constructs and then attempts to parse out the path. It isn't purely a runtime process. They can all handle dynamic paths to some extent, but you need to make it easy for them. If you write something like `import(srcUrl)` then the build tool won't be able to figure out which files `srcUrl` might match. Something like ``import(`../assets/${name}.png`)``, which includes some parts of the path statically, gives the tooling the hints it needs to import all `.png` files in the `../assets` directory.
108 |
109 | ### `new URL()`
110 |
111 | If you're using Vite then images can be included dynamically using `new URL()`:
112 |
113 | ```vue
114 |
123 |
124 |
125 |
126 |
127 | ```
128 |
129 | There are three important caveats when using this approach:
130 |
131 | 1. You can't start the path with an alias, such as `@`.
132 | 2. Dynamic paths must use template literals (i.e. strings with backticks), passed inline as the first argument to `new URL()`. No other form of dynamic value is supported.
133 | 3. SSR is not supported.
134 |
135 | See [the Vite docs](https://vitejs.dev/guide/assets.html#new-url-url-import-meta-url) for more information.
136 |
137 | ### `import.meta.glob()`
138 |
139 | Vite supports importing many files at once using globs. This is asynchronous by default, but we can use the `eager` option to make the path resolution synchronous:
140 |
141 | ```vue
142 |
150 |
151 |
152 |
153 |
154 | ```
155 |
156 | `import.meta.glob()` returns an object, with property keys being the source file names. Aliases are supported, but they will be expanded out to the equivalent relative path, beginning with `./` or `../` as appropriate.
157 |
158 | Having the relative path as the property key isn't always convenient, but we can map it to something else:
159 |
160 | ```vue
161 |
191 |
192 |
193 |
194 |
195 | ```
196 |
197 | See [the Vite docs](https://vitejs.dev/guide/features.html#glob-import) for more information about glob imports.
198 |
199 | If you're using Vite 2 then you'll need to use `globEager` instead. See [the Vite 2 docs](https://v2.vitejs.dev/guide/features.html#glob-import) for more information.
200 |
201 | ### `require()`
202 |
203 | If you're using a webpack-based build tool, such as Vue CLI, then you can use `require()` to import the images. `require()` behaves a bit like a synchronous version of `import()`. e.g.:
204 |
205 | ```js
206 | const imgUrl = require('../assets/' + name + '.png')
207 | // ... or ...
208 | const imgUrl = require(`../assets/${name}.png`)
209 | ```
210 |
211 | It can also be used directly inside a Vue template:
212 |
213 | ```vue
214 |
215 |
216 |
217 | ```
218 |
219 | Much like with the other approaches described above, `require()` needs a partially static path, so that webpack can figure out which files are possible matches. The following will not work:
220 |
221 | ```vue
222 |
223 |
224 |
225 |
226 | ```
227 |
228 | See [the webpack documentation](https://webpack.js.org/guides/dependency-management/) for more information.
229 |
230 | ## `/public`
231 |
232 | Both Vite and Vue CLI have support for a `/public` folder. This is a special folder for files that should always be included in the build, even though they are not imported anywhere. These files cannot have cache-busting hashes added, as their names need to be left unchanged so you can use them in your code.
233 |
234 | Using `/public` can be a good option if there are a lot of images that never change, making the hashing unnecessary. However, it does come with its own problems.
235 |
236 | In the examples that follow, let's assume we've put our images in `/public/images`.
237 |
238 | ### `/public` with Vite
239 |
240 | If we're using Vite, the special handling for tags like ` ` carries across to files in `/public`. We can use static paths, we just need to start the path with a `/`:
241 |
242 | ```vue-html
243 |
244 |
245 | ```
246 |
247 | Note that we **don't** include `/public` in the path.
248 |
249 | The Vite plugin has special handling for files beginning with `/`. It'll first check whether the file exists in the `/public` folder, then fall back to an import if the file wasn't found. If you've configured a [`base`](https://vitejs.dev/guide/build.html#public-base-path) path, Vite will rewrite the attribute path accordingly.
250 |
251 | If we're working with dynamic paths, or static paths on tags the plugin doesn't understand, then we have to apply the `base` path ourselves.
252 |
253 | For example, if we have `base: '/my-app/'` in our Vite config, we can access that path using `import.meta.env.BASE_URL`:
254 |
255 | ```vue
256 |
262 |
263 |
264 |
265 |
266 | ```
267 |
268 | You can read more about the `/public` folder in [the Vite docs](https://vitejs.dev/guide/assets.html#the-public-directory).
269 |
270 | ### `/public` with Vue CLI
271 |
272 | To use the `/public` folder with Vue CLI, we need to apply the [publicPath](https://cli.vuejs.org/config/#publicpath) ourselves, even for static paths.
273 |
274 | For example, the following code will only work if `publicPath` is set to `/`:
275 |
276 | ```vue-html
277 |
278 | ```
279 |
280 | Vue CLI won't rewrite this path at all, it'll just be left as-is.
281 |
282 | We can access the `publicPath` using `process.env.BASE_URL`:
283 |
284 | ```vue
285 |
289 |
290 |
291 |
292 |
293 | ```
294 |
295 | You can read more about the `/public` folder in [the Vue CLI docs](https://cli.vuejs.org/guide/html-and-static-assets.html#the-public-folder).
296 |
--------------------------------------------------------------------------------
/docs/index.md:
--------------------------------------------------------------------------------
1 |
14 | # Introduction
15 |
16 |
17 |
18 | Thank you to those on the [Vue Land Discord](https://chat.vuejs.org/) and elsewhere who inspired these ideas.
19 |
20 | Recently I've been adding pages to the [Vue Land FAQ](https://vue-land.github.io/faq/) rather than putting them here, so if you want more content like this I suggest taking a look at that FAQ.
21 |
22 |
23 |
24 | This collection of components and patterns is intended as a learning aid for those who are new to Vue.
25 |
26 | Their primary purpose is to illustrate how core Vue 3 features can be combined to create standard UI components. The techniques used are intended to demonstrate idiomatic Vue usage for these types of scenarios. These examples have very limited functionality and are not intended to be production-ready components.
27 |
28 | As with all code, trade-offs have been made and alternative approaches may be better in some cases. The explanation that accompanies each example attempts to discuss some of its shortcomings.
29 |
30 | In pretty much all cases, the styling and accessibility of these components is nowhere near the standard that would be expected of a real component library. Most developers choose to use a third-party component library, not least to avoid having to tackle those problems themselves. Some libraries that are compatible with Vue 3 are listed at the bottom of this page.
31 |
32 | ## Example components
33 |
34 | * [Checkbox](./components/checkbox)
35 | * [Radio](./components/radio)
36 | * [Toggle Switch](./components/toggle-switch)
37 | * [Radio Group](./components/radio-group)
38 | * [Accordion](./components/accordion)
39 | * [Tabs](./components/tabs)
40 |
41 | ## Patterns
42 |
43 | * [Computed with v-model](./patterns/computed-v-model)
44 | * [Global Properties](./patterns/global-properties)
45 | * [Coupled Components with `provide`/`inject`](./patterns/coupled-components-with-provide-inject)
46 |
47 | ## Guides
48 |
49 | * [Working with Image Assets](./guides/working-with-image-assets)
50 | * [Understanding the Vue Source Code](./advanced/understanding-the-vue-source-code)
51 |
52 | ## Exercises
53 |
54 | * [Practice projects](./exercises/) for newcomers to Vue.
55 |
56 | ## Component libraries
57 |
58 | * [Component Libraries](./component-libraries) - A list of the most popular component libraries for Vue 3.
59 |
--------------------------------------------------------------------------------
/docs/patterns/computed-v-model.md:
--------------------------------------------------------------------------------
1 |
4 | # Computed with v-model
5 |
6 | :::info
7 | This page has not yet been updated to cover the `defineModel` macro, which was added in Vue 3.4. The techniques described here should still work, but in some cases it might be better to use `defineModel` instead.
8 | :::
9 |
10 | The principle of one-way data flow, with 'props down, events up', is just an extension of the idea that data should only be modified by its owner. This same idea can be extended to other scenarios, such as using Pinia, where the store is considered the owner of the data and so it should only be mutated by the store.
11 |
12 | This causes problems when working with `v-model`, which attempts to modify the value directly. One way we can address this is by using `computed()` with `get` and `set`.
13 |
14 | There are more complete examples for [Checkbox](../components/checkbox) and [Radio](../components/radio) components, but to reduce it down to the essentials with an ` `:
15 |
16 | ```vue-html
17 |
18 | ```
19 |
20 | With:
21 |
22 | ```js
23 | const inputValue = computed({
24 | get () {
25 | // return the current value
26 | },
27 | set (newValue) {
28 | // Tell the data's owner to update the value
29 | }
30 | })
31 | ```
32 |
33 | So for a prop passed down from the parent component we might do something like this:
34 |
35 | ```js
36 | const inputValue = computed({
37 | get: () => props.title,
38 | set: newValue => emit('update:title', newValue)
39 | })
40 | ```
41 |
42 | Using an event with a name of the form `update:propName` allows it to be used with `v-model` on the parent. The default prop name for this would be `modelValue`. As such, the technique described here is the standard way to 'pass on' a `v-model` from a component's parent to one of its children.
43 |
44 | A similar approach would work for updating data via a Pinia action:
45 |
46 | ```js
47 | const store = useMyStore()
48 |
49 | const inputValue = computed({
50 | get: () => store.title,
51 | set: newValue => store.updateTitle(newValue)
52 | })
53 | ```
54 |
55 | ## Libraries
56 |
57 | This pattern is so common that it can be found in composable libraries:
58 |
59 | - [VueUse - useVModel](https://vueuse.org/core/useVModel/)
60 | - [vue-composable - useVModel](https://pikax.me/vue-composable/composable/misc/vmodel.html)
61 |
62 | ## Alternatives
63 |
64 | It is possible to achieve something similar by avoiding the use of `v-model` on the child and splitting it up into a prop and event instead. e.g.:
65 |
66 | ```html
67 |
68 | ```
69 |
70 | This may be tempting, but it does move more logic into the template, which is usually regarded as a bad thing. It's also worth noting that using `v-model` on native elements, such as ` ` and ``, actually adds some extra functionality that you won't get if you implement your own event listeners. e.g.:
71 |
72 | - For text inputs, `v-model` adds special handling for IME composition.
73 | - For radios, `v-model` supports the use of non-string values for the `value`. It also makes managing the `checked` option much simpler.
74 | - For checkboxes, `v-model` adds support for handling `true-value`, `false-value` and the use of a `value` in conjunction with arrays and sets. As with radios it makes managing the `checked` option much simpler for non-boolean cases.
75 | - For ``, it gives similar benefits to either radios and checkboxes, depending on whether the `multiple` attribute is included.
76 |
77 | These potential problems don't apply when using `v-model` on components, so splitting it up into a prop/event pair is less fraught, but consistently sticking to using a `computed` comes with very little risk and tends to be easier to maintain.
78 |
79 | ## Advanced usage - proxying objects
80 |
81 | A less common scenario involves passing a large object of field values to a form component:
82 |
83 | <<< @/patterns/computed-v-model/proxy-example.vue
84 |
85 | Inside `user-edit-form` we want to provide inputs for each of these 6 properties. But having to write 6 separate `computed` values, one for each input, will quickly get annoying.
86 |
87 | One trick to cut down on the boilerplate is to use a JS `Proxy` to do the sleight-of-hand for the reading and writing of properties instead of a `computed`. We'll still use a single `computed` to ensure everything stays reactive, but one is all we need:
88 |
89 | <<< @/patterns/computed-v-model/user-edit-form.vue
90 |
91 | Putting that all together gives:
92 |
93 |
94 |
95 |
96 |
97 | While it might look a bit fiddly if you aren't used to working with a `Proxy`, most of this code is very reusable and can be hidden away behind a utility function. We could create a similar utility function for performing the same bit of trickery with an object coming from a store.
98 |
99 | The approach does violate another best practice. The usual recommendation is to avoid mutating the properties of an object returned from a `computed`, as they're considered transient. However, we're breaking that rule knowingly here as mutating those properties is the whole point of the approach.
100 |
101 | In theory, it is possible to extend this idea to work with nested objects, though it quickly gets unwieldy trying to make all the relevant copies. It's probably better to rethink your approach in that scenario.
102 |
103 | Another possible extension is to combine this approach with the earlier strategy of using `computed` with `get` and `set`. This gives us something quite powerful, with the option to either replace individual properties or replace the whole object:
104 |
105 | ```js
106 | const model = computed({
107 | get () {
108 | return new Proxy(props.modelValue, {
109 | set (obj, key, value) {
110 | model.value = { ...obj, [key]: value }
111 | return true
112 | }
113 | })
114 | },
115 | set (newValue) {
116 | emit('update:modelValue', newValue)
117 | }
118 | })
119 | ```
120 |
121 | With this version we can assign `model.value = something` or `model.value.firstName = something` and in either case it will be magically converted into an event. That allows for both `v-model="model"` and `v-model="model.firstName"`, whichever one we need.
122 |
--------------------------------------------------------------------------------
/docs/patterns/computed-v-model/proxy-example.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | Bound value: {{ user }}
4 |
5 |
18 |
--------------------------------------------------------------------------------
/docs/patterns/computed-v-model/user-edit-form.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
12 |
33 |
--------------------------------------------------------------------------------
/docs/patterns/coupled-components-with-provide-inject.md:
--------------------------------------------------------------------------------
1 | # Coupled Components with `provide`/`inject`
2 |
3 | There are various ways for components to communicate in Vue. The `provide`/`inject` mechanism is one of them, and it's generally not well understood.
4 |
5 | It's common to hear `provide` and `inject` described as 'long-range props' or 'dependency injection'. While those can be useful ways to think of them, a major use case is for communication between tightly coupled components.
6 |
7 | The term 'coupling' is often used as a criticism of a design, but there are many cases where tightly coupled components make sense. These are cases where a particular component needs to be a child (or deeper descendant) of another, specific component. A few examples:
8 |
9 | 1. An [accordion](../components/accordion) is often implemented using a parent container and expandable child panels.
10 | 2. A [tabs](../components/tabs) component may be broken down into several smaller components, e.g. for the tab buttons and the content containers. These all need to communicate to ensure the correct thing is showing at any given time.
11 | 3. A [radio group](../components/radio-group) or checkbox group, for communicating with the radio/checkbox children.
12 | 4. A map component will need to communicate with marker components.
13 | 5. A table component may need to communicate with headers, rows and cells.
14 |
15 | While it is often possible for these components to communicate using props and events, that only works if one of the components is directly responsible for creating the other. It doesn't work if the two components are both created by a common parent.
16 |
17 | Let's see a quick example:
18 |
19 | ```vue
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | ```
28 |
29 | In this scenario `my-map` and `my-map-marker` can't communicate with each other using props and events without the consuming template doing a lot of the work to pass things along.
30 |
31 | This is where `provide` and `inject` really shine. They allow `my-map` to `provide` values that can then be injected into `my-map-marker`.
32 |
33 | While values can only be provided down the component tree, passing a function allows communication back up the tree. For example, let's say we want `my-map-marker` to be able to register itself with the `my-map` component. We might implement that like this:
34 |
35 | ```js
36 | // my-map.vue
37 | const register = () => {
38 | /* ... various logic ... */
39 |
40 | return { map, unregister }
41 | }
42 |
43 | provide('register-marker', register)
44 | ```
45 |
46 | ```js
47 | // my-map-marker.vue
48 | const register = inject('register-marker')
49 |
50 | const { map, unregister } = register()
51 |
52 | onUnmounted(unregister)
53 | ```
54 |
55 | The usage pattern here is very similar to using a composable. The `register` function behaves much like a `useX` function, returning an object that contains everything the caller might need.
56 |
57 | For more complete examples of this pattern, see the [accordion](../components/accordion) and [tabs](../components/tabs) components.
58 |
59 | While this registration pattern can be useful, it isn't the only way to use `provide` and `inject` for communicating between tightly coupled components. Data and functions can be passed down to emulate props and events respectively. The [Radio Group example](../components/radio-group) does something similar.
60 |
61 | ## Alternatives
62 |
63 | Sometimes it's possible to implement this type of tight coupling using `render` functions and direct manipulation of the VNodes. That requires digging into the internals of Vue, which can lead to some unpleasant surprises if you aren't sure what you're doing. I created a library called [`@skirtle/vue-vnode-utils`](https://skirtles-code.github.io/vue-vnode-utils/) that makes this kind of VNode manipulation a little easier. There's an [accordion example](https://skirtles-code.github.io/vue-vnode-utils/examples#adding-component-v-model) in that library's docs that is functionally very similar to the one mentioned above.
64 |
65 | Another alternative is to use scoped slots, though they require the consuming template to get involved.
66 |
67 | For example:
68 |
69 | ```vue
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 | ```
78 |
79 | The `props` object is created by the `my-map` component and is passed to the ``. The consuming template shown above then passes that on to each `my-map-marker` using `v-bind`.
80 |
81 | For the maps example, this probably isn't the way to go. The extra hassle in the consuming template isn't worth it when the components are that tightly coupled. However, scoped slots tend to be preferable in cases where the components are not tightly coupled, allowing the consuming component to decide which components should be tied together.
82 |
--------------------------------------------------------------------------------
/docs/patterns/global-properties.md:
--------------------------------------------------------------------------------
1 | # Global Properties
2 |
3 | TLDR: You probably want [ES modules](#es-modules) instead.
4 |
5 | In Vue 2 it was possible to create 'global properties' by doing something like:
6 |
7 | ```js
8 | Vue.prototype.$http = axios.create({ /* ... */ })
9 | ```
10 |
11 | This would then be available in all components by accessing `this.$http`.
12 |
13 | In Vue 3 there isn't a `Vue.prototype`, but there are various alternatives to solve the same problems. Whether it's appropriate to describe them as 'global', or even as 'properties', is questionable in some cases, but the desired outcome remains the same.
14 |
15 | ## `app.config.globalProperties`
16 |
17 | The most direct replacement in Vue 3 is called `globalProperties`:
18 |
19 | ```js
20 | const app = createApp({ /* ... */ })
21 |
22 | app.config.globalProperties.$http = axios.create({ /* ... */ })
23 | ```
24 |
25 | This allows us to use `this.$http`, just like in Vue 2.
26 |
27 | You'll find this approach used in some official Vue libraries. For example, Vue Router exposes `$router` and `$route`. The mapping helpers provided by Vuex, e.g. `mapState`, all rely on using `this.$store` to access the correct store. These helpers wouldn't be possible using most of the other techniques described on this page.
28 |
29 | However, the use of `globalProperties` in those official libraries shouldn't be seen as an endorsement to use them everywhere. Those libraries have some specific requirements that typically don't apply to application code.
30 |
31 | There are a few problems with using `globalProperties`, including:
32 |
33 | 1. There's no `this` inside `setup`.
34 | 2. The properties exist in components without any explicit definition.
35 |
36 | The `$` prefix tends to be well understood as meaning 'magically injected from outside', but, if the name doesn't give a clear indication of where exactly it came from, it can cause confusion, especially for new developers. However, if this technique is used sparingly, and only for properties that are used often, it is unlikely to cause any serious impediment to understanding.
37 |
38 | What one person describes as 'more explicit', another might call 'verbose' or 'unnecessary boilerplate'. Such terms can be used to express a subjective view of a technique, but they aren't an objective proof of the superiority of one approach over another.
39 |
40 | In particular, these global properties can be useful to expose helper functions to the template. For example, `globalProperties` might be used to share formatting functions:
41 |
42 | ```js
43 | app.config.globalProperties.$format = {
44 | currencyUSD (value) {
45 | return '$' + value.toFixed(2)
46 | }
47 | }
48 | ```
49 |
50 | ```vue-html
51 | {{ $format.currencyUSD(item.unitPrice) }}
52 | ```
53 |
54 | This would be one way to replace *filters*, which no longer exist in Vue 3.
55 |
56 | Other use cases for `globalProperties` in templates might be viewport breakpoints or permissions checks:
57 |
58 | ```vue-html
59 |
60 |
61 |
62 |
63 | ```
64 |
65 | An alternative in this case would be to use a component instead, which we'll discuss [later](#using-components-instead-of-properties).
66 |
67 | `globalProperties` work nicely for things you only need in the template, or if you're using the Options API.
68 |
69 | But the lack of availability in `setup` is a major problem, so let's consider some other alternatives to `globalProperties`.
70 |
71 | ## Application-level `provide` / `inject`
72 |
73 | The standard solution for use with the Composition API is to use `provide` on the application and `inject` in `setup`. The latter will usually be wrapped in a dedicated helper function. We see this approach with Vue Router, which has functions such as `useRouter` and `useRoute` implemented this way.
74 |
75 | Returning to the earlier example for `axios`:
76 |
77 | ```js
78 | const app = createApp({ /* ... */ })
79 | const http = axios.create({ /* ... */ })
80 |
81 | app.provide('http', http)
82 | ```
83 |
84 | While we could use `inject('http')` directly in each component, it'd be better to create a wrapper that hides the implementation details behind an abstraction:
85 |
86 | ```js
87 | const useHttp = () => {
88 | return inject('http')
89 | }
90 | ```
91 |
92 | In practice, this would often use a `Symbol` instead of a string key, ensuring no naming collisions can occur. This would then be wrapped up in a plugin. A more realistic example might look something like this:
93 |
94 | ```js
95 | // main.js
96 | import { createApp } from 'vue'
97 | import { plugin } from './axiosPlugin.js'
98 |
99 | const app = createApp({ /* ... */})
100 | app.use(plugin)
101 | ```
102 |
103 | ```js
104 | // axiosPlugin.js
105 | import { inject } from 'vue'
106 | import axios from 'axios'
107 |
108 | const injectionKey = Symbol('http')
109 |
110 | export const useHttp = () => inject(injectionKey)
111 |
112 | export const plugin = {
113 | install (app) {
114 | const http = axios.create({ /* ... */ })
115 | app.provide(injectionKey, http)
116 |
117 | // It is common to use both `app.config.globalProperties`
118 | // and `provide` in the same plugin
119 | app.config.globalProperties.$http = http
120 | }
121 | }
122 | ```
123 |
124 | ```vue
125 |
130 | ```
131 |
132 | ## ES modules
133 |
134 | While the techniques above can be very useful, in many cases there's no need to reach for a Vue-specific solution at all. ES modules are often more than adequate for sharing 'global' values.
135 |
136 | Taking the `axios` example, we could just export the instance from a module:
137 |
138 | ```js
139 | // http.js
140 | export default axios.create({ /* ... */ })
141 | ```
142 |
143 | That can then be imported wherever we need it:
144 |
145 | ```js
146 | import http from './http.js'
147 | ```
148 |
149 | This flips the dependency. Rather than having a value injected from outside, the dependency is an explicit import from a specific location. The gain in explicitness comes with a small loss in the reusability of the component.
150 |
151 | ES modules also work well outside of Vue components. For the `axios` example, it's common to need the same `axios` instance in Pinia actions. While there are other ways that can be achieved, using an ES module is the most widely used in real applications.
152 |
153 | ## Sharing state using Pinia
154 |
155 | It can also be useful to share state globally. We could just use ES modules and Vue's Reactivity APIs to implement shared state ourselves:
156 |
157 | ```js
158 | export default reactive({})
159 | ```
160 |
161 | Then anything that needs this state object can use `import` to pull it in.
162 |
163 | However, using [Pinia](https://pinia.vuejs.org/), the official Vue state management library, provides several benefits:
164 |
165 | - Documented APIs.
166 | - Familiarity among developers.
167 | - Standard usage patterns that, by design, avoid common problems.
168 | - Integration with Vue Devtools.
169 | - Third-party plugins.
170 | - You don't have to maintain the code yourself.
171 |
172 | So if you need a reactive, central store for your state, you should probably be using Pinia.
173 |
174 | ## Global mixins
175 |
176 | This is rarely the right approach, but it is worth being aware that global mixins can be used as an alternative to `globalProperties`. For example:
177 |
178 | ```js
179 | const app = createApp({ /* ... */ })
180 |
181 | app.mixin({
182 | computed: {
183 | $value () {
184 | // We have access to `this` if we need it.
185 | // Using `computed` makes this reactive.
186 | }
187 | }
188 | })
189 | ```
190 |
191 | Global mixins add extra overhead to the creation of every component in your application, which usually makes them unsuitable for anything other than debugging trickery used during development.
192 |
193 | ## Using components instead of properties
194 |
195 | Earlier we saw how `globalProperties` could be used for exposing things like viewport breakpoints of permissions to the template.
196 |
197 | An alternative approach would be to implement these features using components. These would be *renderless components*, just rendering the contents of their slots if the relevant criteria are met. e.g.:
198 |
199 | ```vue-html
200 |
201 |
202 |
203 | ```
204 |
205 | If you want the equivalent of `v-if`/`v-else` you can use two slots:
206 |
207 | ```vue-html
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 | ```
217 |
218 | The `permission-check` component would still need some way of accessing the 'global' data, and for that it would use one of the other techniques described on this page. The key thing about this approach is that only this one component would need to worry about how the global data is passed around, everything else would just use the component. If you need to refactor how the data is passed around it will only impact this one component.
219 |
220 | To give a concrete example of how `permission-check` might be implemented in conjunction with Pinia:
221 |
222 | ```js
223 | import { useAuthStore } from '@/store/auth.js'
224 |
225 | // Using a functional component, so this is effectively just a render function.
226 | // It doesn't render any VNodes of its own, just those created by its slots.
227 | const PermissionCheck = ({ name }, { slots }) => {
228 | const hasPermission = useAuthStore().permissions[name]
229 |
230 | if (hasPermission) {
231 | return slots.allowed?.() || slots.default?.()
232 | }
233 |
234 | return slots.denied?.()
235 | }
236 | ```
237 |
238 | Using a functional component isn't strictly necessary, but they are well suited to creating renderless components like these.
239 |
240 | ## Patching third-party libraries
241 |
242 | Some third-party libraries, especially those ported from Vue 2, add values to `globalProperties` via a plugin, but don't `provide` the value for compatibility with `setup`.
243 |
244 | This is usually relatively easy to patch.
245 |
246 | Let's assume we have a third-party plugin like this:
247 |
248 | ```js
249 | // axiosPlugin.js
250 | import axios from 'axios'
251 |
252 | export default {
253 | install (app) {
254 | app.config.globalProperties.$http = axios.create({ /* ... */ })
255 | }
256 | }
257 | ```
258 |
259 | We can add the `provide` call ourselves from within `main.js`, after the plugin creates the property:
260 |
261 | ```js
262 | // main.js
263 | import { createApp } from 'vue'
264 | import axiosPlugin from './axiosPlugin.js'
265 |
266 | const app = createApp({ /* ... */ })
267 | app.use(axiosPlugin)
268 | app.provide('http', app.config.globalProperties.$http)
269 | ```
270 |
--------------------------------------------------------------------------------
/docs/public/images/cross.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/docs/public/images/tick.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-examples",
3 | "version": "0.0.0",
4 | "private": true,
5 | "scripts": {
6 | "clean": "rimraf dist && rimraf docs/.vitepress/cache",
7 | "dev": "vitepress dev docs",
8 | "build": "vitepress build docs",
9 | "preview": "vitepress preview docs"
10 | },
11 | "devDependencies": {
12 | "rimraf": "^6.0.1",
13 | "vitepress": "^1.3.4"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/pnpm-lock.yaml:
--------------------------------------------------------------------------------
1 | lockfileVersion: '9.0'
2 |
3 | settings:
4 | autoInstallPeers: true
5 | excludeLinksFromLockfile: false
6 |
7 | importers:
8 |
9 | .:
10 | devDependencies:
11 | rimraf:
12 | specifier: ^6.0.1
13 | version: 6.0.1
14 | vitepress:
15 | specifier: ^1.3.4
16 | version: 1.3.4(@algolia/client-search@4.20.0)(postcss@8.4.33)(search-insights@2.10.0)
17 |
18 | packages:
19 |
20 | '@algolia/autocomplete-core@1.9.3':
21 | resolution: {integrity: sha512-009HdfugtGCdC4JdXUbVJClA0q0zh24yyePn+KUGk3rP7j8FEe/m5Yo/z65gn6nP/cM39PxpzqKrL7A6fP6PPw==}
22 |
23 | '@algolia/autocomplete-plugin-algolia-insights@1.9.3':
24 | resolution: {integrity: sha512-a/yTUkcO/Vyy+JffmAnTWbr4/90cLzw+CC3bRbhnULr/EM0fGNvM13oQQ14f2moLMcVDyAx/leczLlAOovhSZg==}
25 | peerDependencies:
26 | search-insights: '>= 1 < 3'
27 |
28 | '@algolia/autocomplete-preset-algolia@1.9.3':
29 | resolution: {integrity: sha512-d4qlt6YmrLMYy95n5TB52wtNDr6EgAIPH81dvvvW8UmuWRgxEtY0NJiPwl/h95JtG2vmRM804M0DSwMCNZlzRA==}
30 | peerDependencies:
31 | '@algolia/client-search': '>= 4.9.1 < 6'
32 | algoliasearch: '>= 4.9.1 < 6'
33 |
34 | '@algolia/autocomplete-shared@1.9.3':
35 | resolution: {integrity: sha512-Wnm9E4Ye6Rl6sTTqjoymD+l8DjSTHsHboVRYrKgEt8Q7UHm9nYbqhN/i0fhUYA3OAEH7WA8x3jfpnmJm3rKvaQ==}
36 | peerDependencies:
37 | '@algolia/client-search': '>= 4.9.1 < 6'
38 | algoliasearch: '>= 4.9.1 < 6'
39 |
40 | '@algolia/cache-browser-local-storage@4.20.0':
41 | resolution: {integrity: sha512-uujahcBt4DxduBTvYdwO3sBfHuJvJokiC3BP1+O70fglmE1ShkH8lpXqZBac1rrU3FnNYSUs4pL9lBdTKeRPOQ==}
42 |
43 | '@algolia/cache-common@4.20.0':
44 | resolution: {integrity: sha512-vCfxauaZutL3NImzB2G9LjLt36vKAckc6DhMp05An14kVo8F1Yofb6SIl6U3SaEz8pG2QOB9ptwM5c+zGevwIQ==}
45 |
46 | '@algolia/cache-in-memory@4.20.0':
47 | resolution: {integrity: sha512-Wm9ak/IaacAZXS4mB3+qF/KCoVSBV6aLgIGFEtQtJwjv64g4ePMapORGmCyulCFwfePaRAtcaTbMcJF+voc/bg==}
48 |
49 | '@algolia/client-account@4.20.0':
50 | resolution: {integrity: sha512-GGToLQvrwo7am4zVkZTnKa72pheQeez/16sURDWm7Seyz+HUxKi3BM6fthVVPUEBhtJ0reyVtuK9ArmnaKl10Q==}
51 |
52 | '@algolia/client-analytics@4.20.0':
53 | resolution: {integrity: sha512-EIr+PdFMOallRdBTHHdKI3CstslgLORQG7844Mq84ib5oVFRVASuuPmG4bXBgiDbcsMLUeOC6zRVJhv1KWI0ug==}
54 |
55 | '@algolia/client-common@4.20.0':
56 | resolution: {integrity: sha512-P3WgMdEss915p+knMMSd/fwiHRHKvDu4DYRrCRaBrsfFw7EQHon+EbRSm4QisS9NYdxbS04kcvNoavVGthyfqQ==}
57 |
58 | '@algolia/client-personalization@4.20.0':
59 | resolution: {integrity: sha512-N9+zx0tWOQsLc3K4PVRDV8GUeOLAY0i445En79Pr3zWB+m67V+n/8w4Kw1C5LlbHDDJcyhMMIlqezh6BEk7xAQ==}
60 |
61 | '@algolia/client-search@4.20.0':
62 | resolution: {integrity: sha512-zgwqnMvhWLdpzKTpd3sGmMlr4c+iS7eyyLGiaO51zDZWGMkpgoNVmltkzdBwxOVXz0RsFMznIxB9zuarUv4TZg==}
63 |
64 | '@algolia/logger-common@4.20.0':
65 | resolution: {integrity: sha512-xouigCMB5WJYEwvoWW5XDv7Z9f0A8VoXJc3VKwlHJw/je+3p2RcDXfksLI4G4lIVncFUYMZx30tP/rsdlvvzHQ==}
66 |
67 | '@algolia/logger-console@4.20.0':
68 | resolution: {integrity: sha512-THlIGG1g/FS63z0StQqDhT6bprUczBI8wnLT3JWvfAQDZX5P6fCg7dG+pIrUBpDIHGszgkqYEqECaKKsdNKOUA==}
69 |
70 | '@algolia/requester-browser-xhr@4.20.0':
71 | resolution: {integrity: sha512-HbzoSjcjuUmYOkcHECkVTwAelmvTlgs48N6Owt4FnTOQdwn0b8pdht9eMgishvk8+F8bal354nhx/xOoTfwiAw==}
72 |
73 | '@algolia/requester-common@4.20.0':
74 | resolution: {integrity: sha512-9h6ye6RY/BkfmeJp7Z8gyyeMrmmWsMOCRBXQDs4mZKKsyVlfIVICpcSibbeYcuUdurLhIlrOUkH3rQEgZzonng==}
75 |
76 | '@algolia/requester-node-http@4.20.0':
77 | resolution: {integrity: sha512-ocJ66L60ABSSTRFnCHIEZpNHv6qTxsBwJEPfYaSBsLQodm0F9ptvalFkHMpvj5DfE22oZrcrLbOYM2bdPJRHng==}
78 |
79 | '@algolia/transporter@4.20.0':
80 | resolution: {integrity: sha512-Lsii1pGWOAISbzeyuf+r/GPhvHMPHSPrTDWNcIzOE1SG1inlJHICaVe2ikuoRjcpgxZNU54Jl+if15SUCsaTUg==}
81 |
82 | '@babel/helper-string-parser@7.25.7':
83 | resolution: {integrity: sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g==}
84 | engines: {node: '>=6.9.0'}
85 |
86 | '@babel/helper-validator-identifier@7.25.7':
87 | resolution: {integrity: sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==}
88 | engines: {node: '>=6.9.0'}
89 |
90 | '@babel/parser@7.25.7':
91 | resolution: {integrity: sha512-aZn7ETtQsjjGG5HruveUK06cU3Hljuhd9Iojm4M8WWv3wLE6OkE5PWbDUkItmMgegmccaITudyuW5RPYrYlgWw==}
92 | engines: {node: '>=6.0.0'}
93 | hasBin: true
94 |
95 | '@babel/types@7.25.7':
96 | resolution: {integrity: sha512-vwIVdXG+j+FOpkwqHRcBgHLYNL7XMkufrlaFvL9o6Ai9sJn9+PdyIL5qa0XzTZw084c+u9LOls53eoZWP/W5WQ==}
97 | engines: {node: '>=6.9.0'}
98 |
99 | '@docsearch/css@3.6.2':
100 | resolution: {integrity: sha512-vKNZepO2j7MrYBTZIGXvlUOIR+v9KRf70FApRgovWrj3GTs1EITz/Xb0AOlm1xsQBp16clVZj1SY/qaOJbQtZw==}
101 |
102 | '@docsearch/js@3.6.2':
103 | resolution: {integrity: sha512-pS4YZF+VzUogYrkblCucQ0Oy2m8Wggk8Kk7lECmZM60hTbaydSIhJTTiCrmoxtBqV8wxORnOqcqqOfbmkkQEcA==}
104 |
105 | '@docsearch/react@3.6.2':
106 | resolution: {integrity: sha512-rtZce46OOkVflCQH71IdbXSFK+S8iJZlUF56XBW5rIgx/eG5qoomC7Ag3anZson1bBac/JFQn7XOBfved/IMRA==}
107 | peerDependencies:
108 | '@types/react': '>= 16.8.0 < 19.0.0'
109 | react: '>= 16.8.0 < 19.0.0'
110 | react-dom: '>= 16.8.0 < 19.0.0'
111 | search-insights: '>= 1 < 3'
112 | peerDependenciesMeta:
113 | '@types/react':
114 | optional: true
115 | react:
116 | optional: true
117 | react-dom:
118 | optional: true
119 | search-insights:
120 | optional: true
121 |
122 | '@esbuild/aix-ppc64@0.21.5':
123 | resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==}
124 | engines: {node: '>=12'}
125 | cpu: [ppc64]
126 | os: [aix]
127 |
128 | '@esbuild/android-arm64@0.21.5':
129 | resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==}
130 | engines: {node: '>=12'}
131 | cpu: [arm64]
132 | os: [android]
133 |
134 | '@esbuild/android-arm@0.21.5':
135 | resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==}
136 | engines: {node: '>=12'}
137 | cpu: [arm]
138 | os: [android]
139 |
140 | '@esbuild/android-x64@0.21.5':
141 | resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==}
142 | engines: {node: '>=12'}
143 | cpu: [x64]
144 | os: [android]
145 |
146 | '@esbuild/darwin-arm64@0.21.5':
147 | resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==}
148 | engines: {node: '>=12'}
149 | cpu: [arm64]
150 | os: [darwin]
151 |
152 | '@esbuild/darwin-x64@0.21.5':
153 | resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==}
154 | engines: {node: '>=12'}
155 | cpu: [x64]
156 | os: [darwin]
157 |
158 | '@esbuild/freebsd-arm64@0.21.5':
159 | resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==}
160 | engines: {node: '>=12'}
161 | cpu: [arm64]
162 | os: [freebsd]
163 |
164 | '@esbuild/freebsd-x64@0.21.5':
165 | resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==}
166 | engines: {node: '>=12'}
167 | cpu: [x64]
168 | os: [freebsd]
169 |
170 | '@esbuild/linux-arm64@0.21.5':
171 | resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==}
172 | engines: {node: '>=12'}
173 | cpu: [arm64]
174 | os: [linux]
175 |
176 | '@esbuild/linux-arm@0.21.5':
177 | resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==}
178 | engines: {node: '>=12'}
179 | cpu: [arm]
180 | os: [linux]
181 |
182 | '@esbuild/linux-ia32@0.21.5':
183 | resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==}
184 | engines: {node: '>=12'}
185 | cpu: [ia32]
186 | os: [linux]
187 |
188 | '@esbuild/linux-loong64@0.21.5':
189 | resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==}
190 | engines: {node: '>=12'}
191 | cpu: [loong64]
192 | os: [linux]
193 |
194 | '@esbuild/linux-mips64el@0.21.5':
195 | resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==}
196 | engines: {node: '>=12'}
197 | cpu: [mips64el]
198 | os: [linux]
199 |
200 | '@esbuild/linux-ppc64@0.21.5':
201 | resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==}
202 | engines: {node: '>=12'}
203 | cpu: [ppc64]
204 | os: [linux]
205 |
206 | '@esbuild/linux-riscv64@0.21.5':
207 | resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==}
208 | engines: {node: '>=12'}
209 | cpu: [riscv64]
210 | os: [linux]
211 |
212 | '@esbuild/linux-s390x@0.21.5':
213 | resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==}
214 | engines: {node: '>=12'}
215 | cpu: [s390x]
216 | os: [linux]
217 |
218 | '@esbuild/linux-x64@0.21.5':
219 | resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==}
220 | engines: {node: '>=12'}
221 | cpu: [x64]
222 | os: [linux]
223 |
224 | '@esbuild/netbsd-x64@0.21.5':
225 | resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==}
226 | engines: {node: '>=12'}
227 | cpu: [x64]
228 | os: [netbsd]
229 |
230 | '@esbuild/openbsd-x64@0.21.5':
231 | resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==}
232 | engines: {node: '>=12'}
233 | cpu: [x64]
234 | os: [openbsd]
235 |
236 | '@esbuild/sunos-x64@0.21.5':
237 | resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==}
238 | engines: {node: '>=12'}
239 | cpu: [x64]
240 | os: [sunos]
241 |
242 | '@esbuild/win32-arm64@0.21.5':
243 | resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==}
244 | engines: {node: '>=12'}
245 | cpu: [arm64]
246 | os: [win32]
247 |
248 | '@esbuild/win32-ia32@0.21.5':
249 | resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==}
250 | engines: {node: '>=12'}
251 | cpu: [ia32]
252 | os: [win32]
253 |
254 | '@esbuild/win32-x64@0.21.5':
255 | resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==}
256 | engines: {node: '>=12'}
257 | cpu: [x64]
258 | os: [win32]
259 |
260 | '@isaacs/cliui@8.0.2':
261 | resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
262 | engines: {node: '>=12'}
263 |
264 | '@jridgewell/sourcemap-codec@1.5.0':
265 | resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==}
266 |
267 | '@rollup/rollup-android-arm-eabi@4.24.0':
268 | resolution: {integrity: sha512-Q6HJd7Y6xdB48x8ZNVDOqsbh2uByBhgK8PiQgPhwkIw/HC/YX5Ghq2mQY5sRMZWHb3VsFkWooUVOZHKr7DmDIA==}
269 | cpu: [arm]
270 | os: [android]
271 |
272 | '@rollup/rollup-android-arm64@4.24.0':
273 | resolution: {integrity: sha512-ijLnS1qFId8xhKjT81uBHuuJp2lU4x2yxa4ctFPtG+MqEE6+C5f/+X/bStmxapgmwLwiL3ih122xv8kVARNAZA==}
274 | cpu: [arm64]
275 | os: [android]
276 |
277 | '@rollup/rollup-darwin-arm64@4.24.0':
278 | resolution: {integrity: sha512-bIv+X9xeSs1XCk6DVvkO+S/z8/2AMt/2lMqdQbMrmVpgFvXlmde9mLcbQpztXm1tajC3raFDqegsH18HQPMYtA==}
279 | cpu: [arm64]
280 | os: [darwin]
281 |
282 | '@rollup/rollup-darwin-x64@4.24.0':
283 | resolution: {integrity: sha512-X6/nOwoFN7RT2svEQWUsW/5C/fYMBe4fnLK9DQk4SX4mgVBiTA9h64kjUYPvGQ0F/9xwJ5U5UfTbl6BEjaQdBQ==}
284 | cpu: [x64]
285 | os: [darwin]
286 |
287 | '@rollup/rollup-linux-arm-gnueabihf@4.24.0':
288 | resolution: {integrity: sha512-0KXvIJQMOImLCVCz9uvvdPgfyWo93aHHp8ui3FrtOP57svqrF/roSSR5pjqL2hcMp0ljeGlU4q9o/rQaAQ3AYA==}
289 | cpu: [arm]
290 | os: [linux]
291 |
292 | '@rollup/rollup-linux-arm-musleabihf@4.24.0':
293 | resolution: {integrity: sha512-it2BW6kKFVh8xk/BnHfakEeoLPv8STIISekpoF+nBgWM4d55CZKc7T4Dx1pEbTnYm/xEKMgy1MNtYuoA8RFIWw==}
294 | cpu: [arm]
295 | os: [linux]
296 |
297 | '@rollup/rollup-linux-arm64-gnu@4.24.0':
298 | resolution: {integrity: sha512-i0xTLXjqap2eRfulFVlSnM5dEbTVque/3Pi4g2y7cxrs7+a9De42z4XxKLYJ7+OhE3IgxvfQM7vQc43bwTgPwA==}
299 | cpu: [arm64]
300 | os: [linux]
301 |
302 | '@rollup/rollup-linux-arm64-musl@4.24.0':
303 | resolution: {integrity: sha512-9E6MKUJhDuDh604Qco5yP/3qn3y7SLXYuiC0Rpr89aMScS2UAmK1wHP2b7KAa1nSjWJc/f/Lc0Wl1L47qjiyQw==}
304 | cpu: [arm64]
305 | os: [linux]
306 |
307 | '@rollup/rollup-linux-powerpc64le-gnu@4.24.0':
308 | resolution: {integrity: sha512-2XFFPJ2XMEiF5Zi2EBf4h73oR1V/lycirxZxHZNc93SqDN/IWhYYSYj8I9381ikUFXZrz2v7r2tOVk2NBwxrWw==}
309 | cpu: [ppc64]
310 | os: [linux]
311 |
312 | '@rollup/rollup-linux-riscv64-gnu@4.24.0':
313 | resolution: {integrity: sha512-M3Dg4hlwuntUCdzU7KjYqbbd+BLq3JMAOhCKdBE3TcMGMZbKkDdJ5ivNdehOssMCIokNHFOsv7DO4rlEOfyKpg==}
314 | cpu: [riscv64]
315 | os: [linux]
316 |
317 | '@rollup/rollup-linux-s390x-gnu@4.24.0':
318 | resolution: {integrity: sha512-mjBaoo4ocxJppTorZVKWFpy1bfFj9FeCMJqzlMQGjpNPY9JwQi7OuS1axzNIk0nMX6jSgy6ZURDZ2w0QW6D56g==}
319 | cpu: [s390x]
320 | os: [linux]
321 |
322 | '@rollup/rollup-linux-x64-gnu@4.24.0':
323 | resolution: {integrity: sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==}
324 | cpu: [x64]
325 | os: [linux]
326 |
327 | '@rollup/rollup-linux-x64-musl@4.24.0':
328 | resolution: {integrity: sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ==}
329 | cpu: [x64]
330 | os: [linux]
331 |
332 | '@rollup/rollup-win32-arm64-msvc@4.24.0':
333 | resolution: {integrity: sha512-VXBrnPWgBpVDCVY6XF3LEW0pOU51KbaHhccHw6AS6vBWIC60eqsH19DAeeObl+g8nKAz04QFdl/Cefta0xQtUQ==}
334 | cpu: [arm64]
335 | os: [win32]
336 |
337 | '@rollup/rollup-win32-ia32-msvc@4.24.0':
338 | resolution: {integrity: sha512-xrNcGDU0OxVcPTH/8n/ShH4UevZxKIO6HJFK0e15XItZP2UcaiLFd5kiX7hJnqCbSztUF8Qot+JWBC/QXRPYWQ==}
339 | cpu: [ia32]
340 | os: [win32]
341 |
342 | '@rollup/rollup-win32-x64-msvc@4.24.0':
343 | resolution: {integrity: sha512-fbMkAF7fufku0N2dE5TBXcNlg0pt0cJue4xBRE2Qc5Vqikxr4VCgKj/ht6SMdFcOacVA9rqF70APJ8RN/4vMJw==}
344 | cpu: [x64]
345 | os: [win32]
346 |
347 | '@shikijs/core@1.21.0':
348 | resolution: {integrity: sha512-zAPMJdiGuqXpZQ+pWNezQAk5xhzRXBNiECFPcJLtUdsFM3f//G95Z15EHTnHchYycU8kIIysqGgxp8OVSj1SPQ==}
349 |
350 | '@shikijs/engine-javascript@1.21.0':
351 | resolution: {integrity: sha512-jxQHNtVP17edFW4/0vICqAVLDAxmyV31MQJL4U/Kg+heQALeKYVOWo0sMmEZ18FqBt+9UCdyqGKYE7bLRtk9mg==}
352 |
353 | '@shikijs/engine-oniguruma@1.21.0':
354 | resolution: {integrity: sha512-AIZ76XocENCrtYzVU7S4GY/HL+tgHGbVU+qhiDyNw1qgCA5OSi4B4+HY4BtAoJSMGuD/L5hfTzoRVbzEm2WTvg==}
355 |
356 | '@shikijs/transformers@1.21.0':
357 | resolution: {integrity: sha512-aA+XGGSzipcvqdsOYL8l6Q2RYiMuJNdhdt9eZnkJmW+wjSOixN/I7dBq3fISwvEMDlawrtuXM3eybLCEC+Fjlg==}
358 |
359 | '@shikijs/types@1.21.0':
360 | resolution: {integrity: sha512-tzndANDhi5DUndBtpojEq/42+dpUF2wS7wdCDQaFtIXm3Rd1QkrcVgSSRLOvEwexekihOXfbYJINW37g96tJRw==}
361 |
362 | '@shikijs/vscode-textmate@9.2.2':
363 | resolution: {integrity: sha512-TMp15K+GGYrWlZM8+Lnj9EaHEFmOen0WJBrfa17hF7taDOYthuPPV0GWzfd/9iMij0akS/8Yw2ikquH7uVi/fg==}
364 |
365 | '@types/estree@1.0.6':
366 | resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==}
367 |
368 | '@types/hast@3.0.4':
369 | resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==}
370 |
371 | '@types/linkify-it@5.0.0':
372 | resolution: {integrity: sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==}
373 |
374 | '@types/markdown-it@14.1.2':
375 | resolution: {integrity: sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==}
376 |
377 | '@types/mdast@4.0.4':
378 | resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==}
379 |
380 | '@types/mdurl@2.0.0':
381 | resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==}
382 |
383 | '@types/unist@3.0.3':
384 | resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==}
385 |
386 | '@types/web-bluetooth@0.0.20':
387 | resolution: {integrity: sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==}
388 |
389 | '@ungap/structured-clone@1.2.0':
390 | resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==}
391 |
392 | '@vitejs/plugin-vue@5.1.4':
393 | resolution: {integrity: sha512-N2XSI2n3sQqp5w7Y/AN/L2XDjBIRGqXko+eDp42sydYSBeJuSm5a1sLf8zakmo8u7tA8NmBgoDLA1HeOESjp9A==}
394 | engines: {node: ^18.0.0 || >=20.0.0}
395 | peerDependencies:
396 | vite: ^5.0.0
397 | vue: ^3.2.25
398 |
399 | '@vue/compiler-core@3.5.11':
400 | resolution: {integrity: sha512-PwAdxs7/9Hc3ieBO12tXzmTD+Ln4qhT/56S+8DvrrZ4kLDn4Z/AMUr8tXJD0axiJBS0RKIoNaR0yMuQB9v9Udg==}
401 |
402 | '@vue/compiler-dom@3.5.11':
403 | resolution: {integrity: sha512-pyGf8zdbDDRkBrEzf8p7BQlMKNNF5Fk/Cf/fQ6PiUz9at4OaUfyXW0dGJTo2Vl1f5U9jSLCNf0EZJEogLXoeew==}
404 |
405 | '@vue/compiler-sfc@3.5.11':
406 | resolution: {integrity: sha512-gsbBtT4N9ANXXepprle+X9YLg2htQk1sqH/qGJ/EApl+dgpUBdTv3yP7YlR535uHZY3n6XaR0/bKo0BgwwDniw==}
407 |
408 | '@vue/compiler-ssr@3.5.11':
409 | resolution: {integrity: sha512-P4+GPjOuC2aFTk1Z4WANvEhyOykcvEd5bIj2KVNGKGfM745LaXGr++5njpdBTzVz5pZifdlR1kpYSJJpIlSePA==}
410 |
411 | '@vue/devtools-api@7.4.6':
412 | resolution: {integrity: sha512-XipBV5k0/IfTr0sNBDTg7OBUCp51cYMMXyPxLXJZ4K/wmUeMqt8cVdr2ZZGOFq+si/jTyCYnNxeKoyev5DOUUA==}
413 |
414 | '@vue/devtools-kit@7.4.6':
415 | resolution: {integrity: sha512-NbYBwPWgEic1AOd9bWExz9weBzFdjiIfov0yRn4DrRfR+EQJCI9dn4I0XS7IxYGdkmUJi8mFW42LLk18WsGqew==}
416 |
417 | '@vue/devtools-shared@7.4.6':
418 | resolution: {integrity: sha512-rPeSBzElnHYMB05Cc056BQiJpgocQjY8XVulgni+O9a9Gr9tNXgPteSzFFD+fT/iWMxNuUgGKs9CuW5DZewfIg==}
419 |
420 | '@vue/reactivity@3.5.11':
421 | resolution: {integrity: sha512-Nqo5VZEn8MJWlCce8XoyVqHZbd5P2NH+yuAaFzuNSR96I+y1cnuUiq7xfSG+kyvLSiWmaHTKP1r3OZY4mMD50w==}
422 |
423 | '@vue/runtime-core@3.5.11':
424 | resolution: {integrity: sha512-7PsxFGqwfDhfhh0OcDWBG1DaIQIVOLgkwA5q6MtkPiDFjp5gohVnJEahSktwSFLq7R5PtxDKy6WKURVN1UDbzA==}
425 |
426 | '@vue/runtime-dom@3.5.11':
427 | resolution: {integrity: sha512-GNghjecT6IrGf0UhuYmpgaOlN7kxzQBhxWEn08c/SQDxv1yy4IXI1bn81JgEpQ4IXjRxWtPyI8x0/7TF5rPfYQ==}
428 |
429 | '@vue/server-renderer@3.5.11':
430 | resolution: {integrity: sha512-cVOwYBxR7Wb1B1FoxYvtjJD8X/9E5nlH4VSkJy2uMA1MzYNdzAAB//l8nrmN9py/4aP+3NjWukf9PZ3TeWULaA==}
431 | peerDependencies:
432 | vue: 3.5.11
433 |
434 | '@vue/shared@3.5.11':
435 | resolution: {integrity: sha512-W8GgysJVnFo81FthhzurdRAWP/byq3q2qIw70e0JWblzVhjgOMiC2GyovXrZTFQJnFVryYaKGP3Tc9vYzYm6PQ==}
436 |
437 | '@vueuse/core@11.1.0':
438 | resolution: {integrity: sha512-P6dk79QYA6sKQnghrUz/1tHi0n9mrb/iO1WTMk/ElLmTyNqgDeSZ3wcDf6fRBGzRJbeG1dxzEOvLENMjr+E3fg==}
439 |
440 | '@vueuse/integrations@11.1.0':
441 | resolution: {integrity: sha512-O2ZgrAGPy0qAjpoI2YR3egNgyEqwG85fxfwmA9BshRIGjV4G6yu6CfOPpMHAOoCD+UfsIl7Vb1bXJ6ifrHYDDA==}
442 | peerDependencies:
443 | async-validator: ^4
444 | axios: ^1
445 | change-case: ^5
446 | drauu: ^0.4
447 | focus-trap: ^7
448 | fuse.js: ^7
449 | idb-keyval: ^6
450 | jwt-decode: ^4
451 | nprogress: ^0.2
452 | qrcode: ^1.5
453 | sortablejs: ^1
454 | universal-cookie: ^7
455 | peerDependenciesMeta:
456 | async-validator:
457 | optional: true
458 | axios:
459 | optional: true
460 | change-case:
461 | optional: true
462 | drauu:
463 | optional: true
464 | focus-trap:
465 | optional: true
466 | fuse.js:
467 | optional: true
468 | idb-keyval:
469 | optional: true
470 | jwt-decode:
471 | optional: true
472 | nprogress:
473 | optional: true
474 | qrcode:
475 | optional: true
476 | sortablejs:
477 | optional: true
478 | universal-cookie:
479 | optional: true
480 |
481 | '@vueuse/metadata@11.1.0':
482 | resolution: {integrity: sha512-l9Q502TBTaPYGanl1G+hPgd3QX5s4CGnpXriVBR5fEZ/goI6fvDaVmIl3Td8oKFurOxTmbXvBPSsgrd6eu6HYg==}
483 |
484 | '@vueuse/shared@11.1.0':
485 | resolution: {integrity: sha512-YUtIpY122q7osj+zsNMFAfMTubGz0sn5QzE5gPzAIiCmtt2ha3uQUY1+JPyL4gRCTsLPX82Y9brNbo/aqlA91w==}
486 |
487 | algoliasearch@4.20.0:
488 | resolution: {integrity: sha512-y+UHEjnOItoNy0bYO+WWmLWBlPwDjKHW6mNHrPi0NkuhpQOOEbrkwQH/wgKFDLh7qlKjzoKeiRtlpewDPDG23g==}
489 |
490 | ansi-regex@5.0.1:
491 | resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
492 | engines: {node: '>=8'}
493 |
494 | ansi-regex@6.1.0:
495 | resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==}
496 | engines: {node: '>=12'}
497 |
498 | ansi-styles@4.3.0:
499 | resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
500 | engines: {node: '>=8'}
501 |
502 | ansi-styles@6.2.1:
503 | resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==}
504 | engines: {node: '>=12'}
505 |
506 | balanced-match@1.0.2:
507 | resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
508 |
509 | birpc@0.2.17:
510 | resolution: {integrity: sha512-+hkTxhot+dWsLpp3gia5AkVHIsKlZybNT5gIYiDlNzJrmYPcTM9k5/w2uaj3IPpd7LlEYpmCj4Jj1nC41VhDFg==}
511 |
512 | brace-expansion@2.0.1:
513 | resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
514 |
515 | ccount@2.0.1:
516 | resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==}
517 |
518 | character-entities-html4@2.1.0:
519 | resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==}
520 |
521 | character-entities-legacy@3.0.0:
522 | resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==}
523 |
524 | color-convert@2.0.1:
525 | resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
526 | engines: {node: '>=7.0.0'}
527 |
528 | color-name@1.1.4:
529 | resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
530 |
531 | comma-separated-tokens@2.0.3:
532 | resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==}
533 |
534 | copy-anything@3.0.5:
535 | resolution: {integrity: sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==}
536 | engines: {node: '>=12.13'}
537 |
538 | cross-spawn@7.0.3:
539 | resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
540 | engines: {node: '>= 8'}
541 |
542 | csstype@3.1.3:
543 | resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
544 |
545 | dequal@2.0.3:
546 | resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
547 | engines: {node: '>=6'}
548 |
549 | devlop@1.1.0:
550 | resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==}
551 |
552 | eastasianwidth@0.2.0:
553 | resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
554 |
555 | emoji-regex@8.0.0:
556 | resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
557 |
558 | emoji-regex@9.2.2:
559 | resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
560 |
561 | entities@4.5.0:
562 | resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
563 | engines: {node: '>=0.12'}
564 |
565 | esbuild@0.21.5:
566 | resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==}
567 | engines: {node: '>=12'}
568 | hasBin: true
569 |
570 | estree-walker@2.0.2:
571 | resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
572 |
573 | focus-trap@7.5.4:
574 | resolution: {integrity: sha512-N7kHdlgsO/v+iD/dMoJKtsSqs5Dz/dXZVebRgJw23LDk+jMi/974zyiOYDziY2JPp8xivq9BmUGwIJMiuSBi7w==}
575 |
576 | foreground-child@3.3.0:
577 | resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==}
578 | engines: {node: '>=14'}
579 |
580 | fsevents@2.3.3:
581 | resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
582 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
583 | os: [darwin]
584 |
585 | glob@11.0.0:
586 | resolution: {integrity: sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==}
587 | engines: {node: 20 || >=22}
588 | hasBin: true
589 |
590 | hast-util-to-html@9.0.3:
591 | resolution: {integrity: sha512-M17uBDzMJ9RPCqLMO92gNNUDuBSq10a25SDBI08iCCxmorf4Yy6sYHK57n9WAbRAAaU+DuR4W6GN9K4DFZesYg==}
592 |
593 | hast-util-whitespace@3.0.0:
594 | resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==}
595 |
596 | hookable@5.5.3:
597 | resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==}
598 |
599 | html-void-elements@3.0.0:
600 | resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==}
601 |
602 | is-fullwidth-code-point@3.0.0:
603 | resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
604 | engines: {node: '>=8'}
605 |
606 | is-what@4.1.16:
607 | resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==}
608 | engines: {node: '>=12.13'}
609 |
610 | isexe@2.0.0:
611 | resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
612 |
613 | jackspeak@4.0.2:
614 | resolution: {integrity: sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==}
615 | engines: {node: 20 || >=22}
616 |
617 | lru-cache@11.0.1:
618 | resolution: {integrity: sha512-CgeuL5uom6j/ZVrg7G/+1IXqRY8JXX4Hghfy5YE0EhoYQWvndP1kufu58cmZLNIDKnRhZrXfdS9urVWx98AipQ==}
619 | engines: {node: 20 || >=22}
620 |
621 | magic-string@0.30.11:
622 | resolution: {integrity: sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==}
623 |
624 | mark.js@8.11.1:
625 | resolution: {integrity: sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==}
626 |
627 | mdast-util-to-hast@13.2.0:
628 | resolution: {integrity: sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==}
629 |
630 | micromark-util-character@2.1.0:
631 | resolution: {integrity: sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==}
632 |
633 | micromark-util-encode@2.0.0:
634 | resolution: {integrity: sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==}
635 |
636 | micromark-util-sanitize-uri@2.0.0:
637 | resolution: {integrity: sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==}
638 |
639 | micromark-util-symbol@2.0.0:
640 | resolution: {integrity: sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==}
641 |
642 | micromark-util-types@2.0.0:
643 | resolution: {integrity: sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==}
644 |
645 | minimatch@10.0.1:
646 | resolution: {integrity: sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==}
647 | engines: {node: 20 || >=22}
648 |
649 | minipass@7.1.2:
650 | resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
651 | engines: {node: '>=16 || 14 >=14.17'}
652 |
653 | minisearch@7.1.0:
654 | resolution: {integrity: sha512-tv7c/uefWdEhcu6hvrfTihflgeEi2tN6VV7HJnCjK6VxM75QQJh4t9FwJCsA2EsRS8LCnu3W87CuGPWMocOLCA==}
655 |
656 | mitt@3.0.1:
657 | resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==}
658 |
659 | nanoid@3.3.7:
660 | resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==}
661 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
662 | hasBin: true
663 |
664 | oniguruma-to-js@0.4.3:
665 | resolution: {integrity: sha512-X0jWUcAlxORhOqqBREgPMgnshB7ZGYszBNspP+tS9hPD3l13CdaXcHbgImoHUHlrvGx/7AvFEkTRhAGYh+jzjQ==}
666 |
667 | package-json-from-dist@1.0.1:
668 | resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==}
669 |
670 | path-key@3.1.1:
671 | resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
672 | engines: {node: '>=8'}
673 |
674 | path-scurry@2.0.0:
675 | resolution: {integrity: sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==}
676 | engines: {node: 20 || >=22}
677 |
678 | perfect-debounce@1.0.0:
679 | resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==}
680 |
681 | picocolors@1.0.0:
682 | resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==}
683 |
684 | picocolors@1.1.0:
685 | resolution: {integrity: sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==}
686 |
687 | postcss@8.4.33:
688 | resolution: {integrity: sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==}
689 | engines: {node: ^10 || ^12 || >=14}
690 |
691 | postcss@8.4.47:
692 | resolution: {integrity: sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==}
693 | engines: {node: ^10 || ^12 || >=14}
694 |
695 | preact@10.13.2:
696 | resolution: {integrity: sha512-q44QFLhOhty2Bd0Y46fnYW0gD/cbVM9dUVtNTDKPcdXSMA7jfY+Jpd6rk3GB0lcQss0z5s/6CmVP0Z/hV+g6pw==}
697 |
698 | property-information@6.5.0:
699 | resolution: {integrity: sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==}
700 |
701 | regex@4.3.3:
702 | resolution: {integrity: sha512-r/AadFO7owAq1QJVeZ/nq9jNS1vyZt+6t1p/E59B56Rn2GCya+gr1KSyOzNL/er+r+B7phv5jG2xU2Nz1YkmJg==}
703 |
704 | rfdc@1.4.1:
705 | resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==}
706 |
707 | rimraf@6.0.1:
708 | resolution: {integrity: sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==}
709 | engines: {node: 20 || >=22}
710 | hasBin: true
711 |
712 | rollup@4.24.0:
713 | resolution: {integrity: sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg==}
714 | engines: {node: '>=18.0.0', npm: '>=8.0.0'}
715 | hasBin: true
716 |
717 | search-insights@2.10.0:
718 | resolution: {integrity: sha512-pQGrOE56QuTRmq4NzliRZe9rv914hBMBjOviuDliDHoIhmBGoyZRlFsPd4RprGGNC4PKdD2Jz54YN4Cmkb44mA==}
719 |
720 | shebang-command@2.0.0:
721 | resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
722 | engines: {node: '>=8'}
723 |
724 | shebang-regex@3.0.0:
725 | resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
726 | engines: {node: '>=8'}
727 |
728 | shiki@1.21.0:
729 | resolution: {integrity: sha512-apCH5BoWTrmHDPGgg3RF8+HAAbEL/CdbYr8rMw7eIrdhCkZHdVGat5mMNlRtd1erNG01VPMIKHNQ0Pj2HMAiog==}
730 |
731 | signal-exit@4.1.0:
732 | resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
733 | engines: {node: '>=14'}
734 |
735 | source-map-js@1.0.2:
736 | resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==}
737 | engines: {node: '>=0.10.0'}
738 |
739 | source-map-js@1.2.1:
740 | resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
741 | engines: {node: '>=0.10.0'}
742 |
743 | space-separated-tokens@2.0.2:
744 | resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==}
745 |
746 | speakingurl@14.0.1:
747 | resolution: {integrity: sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==}
748 | engines: {node: '>=0.10.0'}
749 |
750 | string-width@4.2.3:
751 | resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
752 | engines: {node: '>=8'}
753 |
754 | string-width@5.1.2:
755 | resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==}
756 | engines: {node: '>=12'}
757 |
758 | stringify-entities@4.0.4:
759 | resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==}
760 |
761 | strip-ansi@6.0.1:
762 | resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
763 | engines: {node: '>=8'}
764 |
765 | strip-ansi@7.1.0:
766 | resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==}
767 | engines: {node: '>=12'}
768 |
769 | superjson@2.2.1:
770 | resolution: {integrity: sha512-8iGv75BYOa0xRJHK5vRLEjE2H/i4lulTjzpUXic3Eg8akftYjkmQDa8JARQ42rlczXyFR3IeRoeFCc7RxHsYZA==}
771 | engines: {node: '>=16'}
772 |
773 | tabbable@6.2.0:
774 | resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==}
775 |
776 | to-fast-properties@2.0.0:
777 | resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==}
778 | engines: {node: '>=4'}
779 |
780 | trim-lines@3.0.1:
781 | resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==}
782 |
783 | unist-util-is@6.0.0:
784 | resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==}
785 |
786 | unist-util-position@5.0.0:
787 | resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==}
788 |
789 | unist-util-stringify-position@4.0.0:
790 | resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==}
791 |
792 | unist-util-visit-parents@6.0.1:
793 | resolution: {integrity: sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==}
794 |
795 | unist-util-visit@5.0.0:
796 | resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==}
797 |
798 | vfile-message@4.0.2:
799 | resolution: {integrity: sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==}
800 |
801 | vfile@6.0.3:
802 | resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==}
803 |
804 | vite@5.4.8:
805 | resolution: {integrity: sha512-FqrItQ4DT1NC4zCUqMB4c4AZORMKIa0m8/URVCZ77OZ/QSNeJ54bU1vrFADbDsuwfIPcgknRkmqakQcgnL4GiQ==}
806 | engines: {node: ^18.0.0 || >=20.0.0}
807 | hasBin: true
808 | peerDependencies:
809 | '@types/node': ^18.0.0 || >=20.0.0
810 | less: '*'
811 | lightningcss: ^1.21.0
812 | sass: '*'
813 | sass-embedded: '*'
814 | stylus: '*'
815 | sugarss: '*'
816 | terser: ^5.4.0
817 | peerDependenciesMeta:
818 | '@types/node':
819 | optional: true
820 | less:
821 | optional: true
822 | lightningcss:
823 | optional: true
824 | sass:
825 | optional: true
826 | sass-embedded:
827 | optional: true
828 | stylus:
829 | optional: true
830 | sugarss:
831 | optional: true
832 | terser:
833 | optional: true
834 |
835 | vitepress@1.3.4:
836 | resolution: {integrity: sha512-I1/F6OW1xl3kW4PaIMC6snxjWgf3qfziq2aqsDoFc/Gt41WbcRv++z8zjw8qGRIJ+I4bUW7ZcKFDHHN/jkH9DQ==}
837 | hasBin: true
838 | peerDependencies:
839 | markdown-it-mathjax3: ^4
840 | postcss: ^8
841 | peerDependenciesMeta:
842 | markdown-it-mathjax3:
843 | optional: true
844 | postcss:
845 | optional: true
846 |
847 | vue-demi@0.14.10:
848 | resolution: {integrity: sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==}
849 | engines: {node: '>=12'}
850 | hasBin: true
851 | peerDependencies:
852 | '@vue/composition-api': ^1.0.0-rc.1
853 | vue: ^3.0.0-0 || ^2.6.0
854 | peerDependenciesMeta:
855 | '@vue/composition-api':
856 | optional: true
857 |
858 | vue@3.5.11:
859 | resolution: {integrity: sha512-/8Wurrd9J3lb72FTQS7gRMNQD4nztTtKPmuDuPuhqXmmpD6+skVjAeahNpVzsuky6Sy9gy7wn8UadqPtt9SQIg==}
860 | peerDependencies:
861 | typescript: '*'
862 | peerDependenciesMeta:
863 | typescript:
864 | optional: true
865 |
866 | which@2.0.2:
867 | resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
868 | engines: {node: '>= 8'}
869 | hasBin: true
870 |
871 | wrap-ansi@7.0.0:
872 | resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
873 | engines: {node: '>=10'}
874 |
875 | wrap-ansi@8.1.0:
876 | resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==}
877 | engines: {node: '>=12'}
878 |
879 | zwitch@2.0.4:
880 | resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
881 |
882 | snapshots:
883 |
884 | '@algolia/autocomplete-core@1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0)(search-insights@2.10.0)':
885 | dependencies:
886 | '@algolia/autocomplete-plugin-algolia-insights': 1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0)(search-insights@2.10.0)
887 | '@algolia/autocomplete-shared': 1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0)
888 | transitivePeerDependencies:
889 | - '@algolia/client-search'
890 | - algoliasearch
891 | - search-insights
892 |
893 | '@algolia/autocomplete-plugin-algolia-insights@1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0)(search-insights@2.10.0)':
894 | dependencies:
895 | '@algolia/autocomplete-shared': 1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0)
896 | search-insights: 2.10.0
897 | transitivePeerDependencies:
898 | - '@algolia/client-search'
899 | - algoliasearch
900 |
901 | '@algolia/autocomplete-preset-algolia@1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0)':
902 | dependencies:
903 | '@algolia/autocomplete-shared': 1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0)
904 | '@algolia/client-search': 4.20.0
905 | algoliasearch: 4.20.0
906 |
907 | '@algolia/autocomplete-shared@1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0)':
908 | dependencies:
909 | '@algolia/client-search': 4.20.0
910 | algoliasearch: 4.20.0
911 |
912 | '@algolia/cache-browser-local-storage@4.20.0':
913 | dependencies:
914 | '@algolia/cache-common': 4.20.0
915 |
916 | '@algolia/cache-common@4.20.0': {}
917 |
918 | '@algolia/cache-in-memory@4.20.0':
919 | dependencies:
920 | '@algolia/cache-common': 4.20.0
921 |
922 | '@algolia/client-account@4.20.0':
923 | dependencies:
924 | '@algolia/client-common': 4.20.0
925 | '@algolia/client-search': 4.20.0
926 | '@algolia/transporter': 4.20.0
927 |
928 | '@algolia/client-analytics@4.20.0':
929 | dependencies:
930 | '@algolia/client-common': 4.20.0
931 | '@algolia/client-search': 4.20.0
932 | '@algolia/requester-common': 4.20.0
933 | '@algolia/transporter': 4.20.0
934 |
935 | '@algolia/client-common@4.20.0':
936 | dependencies:
937 | '@algolia/requester-common': 4.20.0
938 | '@algolia/transporter': 4.20.0
939 |
940 | '@algolia/client-personalization@4.20.0':
941 | dependencies:
942 | '@algolia/client-common': 4.20.0
943 | '@algolia/requester-common': 4.20.0
944 | '@algolia/transporter': 4.20.0
945 |
946 | '@algolia/client-search@4.20.0':
947 | dependencies:
948 | '@algolia/client-common': 4.20.0
949 | '@algolia/requester-common': 4.20.0
950 | '@algolia/transporter': 4.20.0
951 |
952 | '@algolia/logger-common@4.20.0': {}
953 |
954 | '@algolia/logger-console@4.20.0':
955 | dependencies:
956 | '@algolia/logger-common': 4.20.0
957 |
958 | '@algolia/requester-browser-xhr@4.20.0':
959 | dependencies:
960 | '@algolia/requester-common': 4.20.0
961 |
962 | '@algolia/requester-common@4.20.0': {}
963 |
964 | '@algolia/requester-node-http@4.20.0':
965 | dependencies:
966 | '@algolia/requester-common': 4.20.0
967 |
968 | '@algolia/transporter@4.20.0':
969 | dependencies:
970 | '@algolia/cache-common': 4.20.0
971 | '@algolia/logger-common': 4.20.0
972 | '@algolia/requester-common': 4.20.0
973 |
974 | '@babel/helper-string-parser@7.25.7': {}
975 |
976 | '@babel/helper-validator-identifier@7.25.7': {}
977 |
978 | '@babel/parser@7.25.7':
979 | dependencies:
980 | '@babel/types': 7.25.7
981 |
982 | '@babel/types@7.25.7':
983 | dependencies:
984 | '@babel/helper-string-parser': 7.25.7
985 | '@babel/helper-validator-identifier': 7.25.7
986 | to-fast-properties: 2.0.0
987 |
988 | '@docsearch/css@3.6.2': {}
989 |
990 | '@docsearch/js@3.6.2(@algolia/client-search@4.20.0)(search-insights@2.10.0)':
991 | dependencies:
992 | '@docsearch/react': 3.6.2(@algolia/client-search@4.20.0)(search-insights@2.10.0)
993 | preact: 10.13.2
994 | transitivePeerDependencies:
995 | - '@algolia/client-search'
996 | - '@types/react'
997 | - react
998 | - react-dom
999 | - search-insights
1000 |
1001 | '@docsearch/react@3.6.2(@algolia/client-search@4.20.0)(search-insights@2.10.0)':
1002 | dependencies:
1003 | '@algolia/autocomplete-core': 1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0)(search-insights@2.10.0)
1004 | '@algolia/autocomplete-preset-algolia': 1.9.3(@algolia/client-search@4.20.0)(algoliasearch@4.20.0)
1005 | '@docsearch/css': 3.6.2
1006 | algoliasearch: 4.20.0
1007 | optionalDependencies:
1008 | search-insights: 2.10.0
1009 | transitivePeerDependencies:
1010 | - '@algolia/client-search'
1011 |
1012 | '@esbuild/aix-ppc64@0.21.5':
1013 | optional: true
1014 |
1015 | '@esbuild/android-arm64@0.21.5':
1016 | optional: true
1017 |
1018 | '@esbuild/android-arm@0.21.5':
1019 | optional: true
1020 |
1021 | '@esbuild/android-x64@0.21.5':
1022 | optional: true
1023 |
1024 | '@esbuild/darwin-arm64@0.21.5':
1025 | optional: true
1026 |
1027 | '@esbuild/darwin-x64@0.21.5':
1028 | optional: true
1029 |
1030 | '@esbuild/freebsd-arm64@0.21.5':
1031 | optional: true
1032 |
1033 | '@esbuild/freebsd-x64@0.21.5':
1034 | optional: true
1035 |
1036 | '@esbuild/linux-arm64@0.21.5':
1037 | optional: true
1038 |
1039 | '@esbuild/linux-arm@0.21.5':
1040 | optional: true
1041 |
1042 | '@esbuild/linux-ia32@0.21.5':
1043 | optional: true
1044 |
1045 | '@esbuild/linux-loong64@0.21.5':
1046 | optional: true
1047 |
1048 | '@esbuild/linux-mips64el@0.21.5':
1049 | optional: true
1050 |
1051 | '@esbuild/linux-ppc64@0.21.5':
1052 | optional: true
1053 |
1054 | '@esbuild/linux-riscv64@0.21.5':
1055 | optional: true
1056 |
1057 | '@esbuild/linux-s390x@0.21.5':
1058 | optional: true
1059 |
1060 | '@esbuild/linux-x64@0.21.5':
1061 | optional: true
1062 |
1063 | '@esbuild/netbsd-x64@0.21.5':
1064 | optional: true
1065 |
1066 | '@esbuild/openbsd-x64@0.21.5':
1067 | optional: true
1068 |
1069 | '@esbuild/sunos-x64@0.21.5':
1070 | optional: true
1071 |
1072 | '@esbuild/win32-arm64@0.21.5':
1073 | optional: true
1074 |
1075 | '@esbuild/win32-ia32@0.21.5':
1076 | optional: true
1077 |
1078 | '@esbuild/win32-x64@0.21.5':
1079 | optional: true
1080 |
1081 | '@isaacs/cliui@8.0.2':
1082 | dependencies:
1083 | string-width: 5.1.2
1084 | string-width-cjs: string-width@4.2.3
1085 | strip-ansi: 7.1.0
1086 | strip-ansi-cjs: strip-ansi@6.0.1
1087 | wrap-ansi: 8.1.0
1088 | wrap-ansi-cjs: wrap-ansi@7.0.0
1089 |
1090 | '@jridgewell/sourcemap-codec@1.5.0': {}
1091 |
1092 | '@rollup/rollup-android-arm-eabi@4.24.0':
1093 | optional: true
1094 |
1095 | '@rollup/rollup-android-arm64@4.24.0':
1096 | optional: true
1097 |
1098 | '@rollup/rollup-darwin-arm64@4.24.0':
1099 | optional: true
1100 |
1101 | '@rollup/rollup-darwin-x64@4.24.0':
1102 | optional: true
1103 |
1104 | '@rollup/rollup-linux-arm-gnueabihf@4.24.0':
1105 | optional: true
1106 |
1107 | '@rollup/rollup-linux-arm-musleabihf@4.24.0':
1108 | optional: true
1109 |
1110 | '@rollup/rollup-linux-arm64-gnu@4.24.0':
1111 | optional: true
1112 |
1113 | '@rollup/rollup-linux-arm64-musl@4.24.0':
1114 | optional: true
1115 |
1116 | '@rollup/rollup-linux-powerpc64le-gnu@4.24.0':
1117 | optional: true
1118 |
1119 | '@rollup/rollup-linux-riscv64-gnu@4.24.0':
1120 | optional: true
1121 |
1122 | '@rollup/rollup-linux-s390x-gnu@4.24.0':
1123 | optional: true
1124 |
1125 | '@rollup/rollup-linux-x64-gnu@4.24.0':
1126 | optional: true
1127 |
1128 | '@rollup/rollup-linux-x64-musl@4.24.0':
1129 | optional: true
1130 |
1131 | '@rollup/rollup-win32-arm64-msvc@4.24.0':
1132 | optional: true
1133 |
1134 | '@rollup/rollup-win32-ia32-msvc@4.24.0':
1135 | optional: true
1136 |
1137 | '@rollup/rollup-win32-x64-msvc@4.24.0':
1138 | optional: true
1139 |
1140 | '@shikijs/core@1.21.0':
1141 | dependencies:
1142 | '@shikijs/engine-javascript': 1.21.0
1143 | '@shikijs/engine-oniguruma': 1.21.0
1144 | '@shikijs/types': 1.21.0
1145 | '@shikijs/vscode-textmate': 9.2.2
1146 | '@types/hast': 3.0.4
1147 | hast-util-to-html: 9.0.3
1148 |
1149 | '@shikijs/engine-javascript@1.21.0':
1150 | dependencies:
1151 | '@shikijs/types': 1.21.0
1152 | '@shikijs/vscode-textmate': 9.2.2
1153 | oniguruma-to-js: 0.4.3
1154 |
1155 | '@shikijs/engine-oniguruma@1.21.0':
1156 | dependencies:
1157 | '@shikijs/types': 1.21.0
1158 | '@shikijs/vscode-textmate': 9.2.2
1159 |
1160 | '@shikijs/transformers@1.21.0':
1161 | dependencies:
1162 | shiki: 1.21.0
1163 |
1164 | '@shikijs/types@1.21.0':
1165 | dependencies:
1166 | '@shikijs/vscode-textmate': 9.2.2
1167 | '@types/hast': 3.0.4
1168 |
1169 | '@shikijs/vscode-textmate@9.2.2': {}
1170 |
1171 | '@types/estree@1.0.6': {}
1172 |
1173 | '@types/hast@3.0.4':
1174 | dependencies:
1175 | '@types/unist': 3.0.3
1176 |
1177 | '@types/linkify-it@5.0.0': {}
1178 |
1179 | '@types/markdown-it@14.1.2':
1180 | dependencies:
1181 | '@types/linkify-it': 5.0.0
1182 | '@types/mdurl': 2.0.0
1183 |
1184 | '@types/mdast@4.0.4':
1185 | dependencies:
1186 | '@types/unist': 3.0.3
1187 |
1188 | '@types/mdurl@2.0.0': {}
1189 |
1190 | '@types/unist@3.0.3': {}
1191 |
1192 | '@types/web-bluetooth@0.0.20': {}
1193 |
1194 | '@ungap/structured-clone@1.2.0': {}
1195 |
1196 | '@vitejs/plugin-vue@5.1.4(vite@5.4.8)(vue@3.5.11)':
1197 | dependencies:
1198 | vite: 5.4.8
1199 | vue: 3.5.11
1200 |
1201 | '@vue/compiler-core@3.5.11':
1202 | dependencies:
1203 | '@babel/parser': 7.25.7
1204 | '@vue/shared': 3.5.11
1205 | entities: 4.5.0
1206 | estree-walker: 2.0.2
1207 | source-map-js: 1.2.1
1208 |
1209 | '@vue/compiler-dom@3.5.11':
1210 | dependencies:
1211 | '@vue/compiler-core': 3.5.11
1212 | '@vue/shared': 3.5.11
1213 |
1214 | '@vue/compiler-sfc@3.5.11':
1215 | dependencies:
1216 | '@babel/parser': 7.25.7
1217 | '@vue/compiler-core': 3.5.11
1218 | '@vue/compiler-dom': 3.5.11
1219 | '@vue/compiler-ssr': 3.5.11
1220 | '@vue/shared': 3.5.11
1221 | estree-walker: 2.0.2
1222 | magic-string: 0.30.11
1223 | postcss: 8.4.47
1224 | source-map-js: 1.2.1
1225 |
1226 | '@vue/compiler-ssr@3.5.11':
1227 | dependencies:
1228 | '@vue/compiler-dom': 3.5.11
1229 | '@vue/shared': 3.5.11
1230 |
1231 | '@vue/devtools-api@7.4.6':
1232 | dependencies:
1233 | '@vue/devtools-kit': 7.4.6
1234 |
1235 | '@vue/devtools-kit@7.4.6':
1236 | dependencies:
1237 | '@vue/devtools-shared': 7.4.6
1238 | birpc: 0.2.17
1239 | hookable: 5.5.3
1240 | mitt: 3.0.1
1241 | perfect-debounce: 1.0.0
1242 | speakingurl: 14.0.1
1243 | superjson: 2.2.1
1244 |
1245 | '@vue/devtools-shared@7.4.6':
1246 | dependencies:
1247 | rfdc: 1.4.1
1248 |
1249 | '@vue/reactivity@3.5.11':
1250 | dependencies:
1251 | '@vue/shared': 3.5.11
1252 |
1253 | '@vue/runtime-core@3.5.11':
1254 | dependencies:
1255 | '@vue/reactivity': 3.5.11
1256 | '@vue/shared': 3.5.11
1257 |
1258 | '@vue/runtime-dom@3.5.11':
1259 | dependencies:
1260 | '@vue/reactivity': 3.5.11
1261 | '@vue/runtime-core': 3.5.11
1262 | '@vue/shared': 3.5.11
1263 | csstype: 3.1.3
1264 |
1265 | '@vue/server-renderer@3.5.11(vue@3.5.11)':
1266 | dependencies:
1267 | '@vue/compiler-ssr': 3.5.11
1268 | '@vue/shared': 3.5.11
1269 | vue: 3.5.11
1270 |
1271 | '@vue/shared@3.5.11': {}
1272 |
1273 | '@vueuse/core@11.1.0(vue@3.5.11)':
1274 | dependencies:
1275 | '@types/web-bluetooth': 0.0.20
1276 | '@vueuse/metadata': 11.1.0
1277 | '@vueuse/shared': 11.1.0(vue@3.5.11)
1278 | vue-demi: 0.14.10(vue@3.5.11)
1279 | transitivePeerDependencies:
1280 | - '@vue/composition-api'
1281 | - vue
1282 |
1283 | '@vueuse/integrations@11.1.0(focus-trap@7.5.4)(vue@3.5.11)':
1284 | dependencies:
1285 | '@vueuse/core': 11.1.0(vue@3.5.11)
1286 | '@vueuse/shared': 11.1.0(vue@3.5.11)
1287 | vue-demi: 0.14.10(vue@3.5.11)
1288 | optionalDependencies:
1289 | focus-trap: 7.5.4
1290 | transitivePeerDependencies:
1291 | - '@vue/composition-api'
1292 | - vue
1293 |
1294 | '@vueuse/metadata@11.1.0': {}
1295 |
1296 | '@vueuse/shared@11.1.0(vue@3.5.11)':
1297 | dependencies:
1298 | vue-demi: 0.14.10(vue@3.5.11)
1299 | transitivePeerDependencies:
1300 | - '@vue/composition-api'
1301 | - vue
1302 |
1303 | algoliasearch@4.20.0:
1304 | dependencies:
1305 | '@algolia/cache-browser-local-storage': 4.20.0
1306 | '@algolia/cache-common': 4.20.0
1307 | '@algolia/cache-in-memory': 4.20.0
1308 | '@algolia/client-account': 4.20.0
1309 | '@algolia/client-analytics': 4.20.0
1310 | '@algolia/client-common': 4.20.0
1311 | '@algolia/client-personalization': 4.20.0
1312 | '@algolia/client-search': 4.20.0
1313 | '@algolia/logger-common': 4.20.0
1314 | '@algolia/logger-console': 4.20.0
1315 | '@algolia/requester-browser-xhr': 4.20.0
1316 | '@algolia/requester-common': 4.20.0
1317 | '@algolia/requester-node-http': 4.20.0
1318 | '@algolia/transporter': 4.20.0
1319 |
1320 | ansi-regex@5.0.1: {}
1321 |
1322 | ansi-regex@6.1.0: {}
1323 |
1324 | ansi-styles@4.3.0:
1325 | dependencies:
1326 | color-convert: 2.0.1
1327 |
1328 | ansi-styles@6.2.1: {}
1329 |
1330 | balanced-match@1.0.2: {}
1331 |
1332 | birpc@0.2.17: {}
1333 |
1334 | brace-expansion@2.0.1:
1335 | dependencies:
1336 | balanced-match: 1.0.2
1337 |
1338 | ccount@2.0.1: {}
1339 |
1340 | character-entities-html4@2.1.0: {}
1341 |
1342 | character-entities-legacy@3.0.0: {}
1343 |
1344 | color-convert@2.0.1:
1345 | dependencies:
1346 | color-name: 1.1.4
1347 |
1348 | color-name@1.1.4: {}
1349 |
1350 | comma-separated-tokens@2.0.3: {}
1351 |
1352 | copy-anything@3.0.5:
1353 | dependencies:
1354 | is-what: 4.1.16
1355 |
1356 | cross-spawn@7.0.3:
1357 | dependencies:
1358 | path-key: 3.1.1
1359 | shebang-command: 2.0.0
1360 | which: 2.0.2
1361 |
1362 | csstype@3.1.3: {}
1363 |
1364 | dequal@2.0.3: {}
1365 |
1366 | devlop@1.1.0:
1367 | dependencies:
1368 | dequal: 2.0.3
1369 |
1370 | eastasianwidth@0.2.0: {}
1371 |
1372 | emoji-regex@8.0.0: {}
1373 |
1374 | emoji-regex@9.2.2: {}
1375 |
1376 | entities@4.5.0: {}
1377 |
1378 | esbuild@0.21.5:
1379 | optionalDependencies:
1380 | '@esbuild/aix-ppc64': 0.21.5
1381 | '@esbuild/android-arm': 0.21.5
1382 | '@esbuild/android-arm64': 0.21.5
1383 | '@esbuild/android-x64': 0.21.5
1384 | '@esbuild/darwin-arm64': 0.21.5
1385 | '@esbuild/darwin-x64': 0.21.5
1386 | '@esbuild/freebsd-arm64': 0.21.5
1387 | '@esbuild/freebsd-x64': 0.21.5
1388 | '@esbuild/linux-arm': 0.21.5
1389 | '@esbuild/linux-arm64': 0.21.5
1390 | '@esbuild/linux-ia32': 0.21.5
1391 | '@esbuild/linux-loong64': 0.21.5
1392 | '@esbuild/linux-mips64el': 0.21.5
1393 | '@esbuild/linux-ppc64': 0.21.5
1394 | '@esbuild/linux-riscv64': 0.21.5
1395 | '@esbuild/linux-s390x': 0.21.5
1396 | '@esbuild/linux-x64': 0.21.5
1397 | '@esbuild/netbsd-x64': 0.21.5
1398 | '@esbuild/openbsd-x64': 0.21.5
1399 | '@esbuild/sunos-x64': 0.21.5
1400 | '@esbuild/win32-arm64': 0.21.5
1401 | '@esbuild/win32-ia32': 0.21.5
1402 | '@esbuild/win32-x64': 0.21.5
1403 |
1404 | estree-walker@2.0.2: {}
1405 |
1406 | focus-trap@7.5.4:
1407 | dependencies:
1408 | tabbable: 6.2.0
1409 |
1410 | foreground-child@3.3.0:
1411 | dependencies:
1412 | cross-spawn: 7.0.3
1413 | signal-exit: 4.1.0
1414 |
1415 | fsevents@2.3.3:
1416 | optional: true
1417 |
1418 | glob@11.0.0:
1419 | dependencies:
1420 | foreground-child: 3.3.0
1421 | jackspeak: 4.0.2
1422 | minimatch: 10.0.1
1423 | minipass: 7.1.2
1424 | package-json-from-dist: 1.0.1
1425 | path-scurry: 2.0.0
1426 |
1427 | hast-util-to-html@9.0.3:
1428 | dependencies:
1429 | '@types/hast': 3.0.4
1430 | '@types/unist': 3.0.3
1431 | ccount: 2.0.1
1432 | comma-separated-tokens: 2.0.3
1433 | hast-util-whitespace: 3.0.0
1434 | html-void-elements: 3.0.0
1435 | mdast-util-to-hast: 13.2.0
1436 | property-information: 6.5.0
1437 | space-separated-tokens: 2.0.2
1438 | stringify-entities: 4.0.4
1439 | zwitch: 2.0.4
1440 |
1441 | hast-util-whitespace@3.0.0:
1442 | dependencies:
1443 | '@types/hast': 3.0.4
1444 |
1445 | hookable@5.5.3: {}
1446 |
1447 | html-void-elements@3.0.0: {}
1448 |
1449 | is-fullwidth-code-point@3.0.0: {}
1450 |
1451 | is-what@4.1.16: {}
1452 |
1453 | isexe@2.0.0: {}
1454 |
1455 | jackspeak@4.0.2:
1456 | dependencies:
1457 | '@isaacs/cliui': 8.0.2
1458 |
1459 | lru-cache@11.0.1: {}
1460 |
1461 | magic-string@0.30.11:
1462 | dependencies:
1463 | '@jridgewell/sourcemap-codec': 1.5.0
1464 |
1465 | mark.js@8.11.1: {}
1466 |
1467 | mdast-util-to-hast@13.2.0:
1468 | dependencies:
1469 | '@types/hast': 3.0.4
1470 | '@types/mdast': 4.0.4
1471 | '@ungap/structured-clone': 1.2.0
1472 | devlop: 1.1.0
1473 | micromark-util-sanitize-uri: 2.0.0
1474 | trim-lines: 3.0.1
1475 | unist-util-position: 5.0.0
1476 | unist-util-visit: 5.0.0
1477 | vfile: 6.0.3
1478 |
1479 | micromark-util-character@2.1.0:
1480 | dependencies:
1481 | micromark-util-symbol: 2.0.0
1482 | micromark-util-types: 2.0.0
1483 |
1484 | micromark-util-encode@2.0.0: {}
1485 |
1486 | micromark-util-sanitize-uri@2.0.0:
1487 | dependencies:
1488 | micromark-util-character: 2.1.0
1489 | micromark-util-encode: 2.0.0
1490 | micromark-util-symbol: 2.0.0
1491 |
1492 | micromark-util-symbol@2.0.0: {}
1493 |
1494 | micromark-util-types@2.0.0: {}
1495 |
1496 | minimatch@10.0.1:
1497 | dependencies:
1498 | brace-expansion: 2.0.1
1499 |
1500 | minipass@7.1.2: {}
1501 |
1502 | minisearch@7.1.0: {}
1503 |
1504 | mitt@3.0.1: {}
1505 |
1506 | nanoid@3.3.7: {}
1507 |
1508 | oniguruma-to-js@0.4.3:
1509 | dependencies:
1510 | regex: 4.3.3
1511 |
1512 | package-json-from-dist@1.0.1: {}
1513 |
1514 | path-key@3.1.1: {}
1515 |
1516 | path-scurry@2.0.0:
1517 | dependencies:
1518 | lru-cache: 11.0.1
1519 | minipass: 7.1.2
1520 |
1521 | perfect-debounce@1.0.0: {}
1522 |
1523 | picocolors@1.0.0:
1524 | optional: true
1525 |
1526 | picocolors@1.1.0: {}
1527 |
1528 | postcss@8.4.33:
1529 | dependencies:
1530 | nanoid: 3.3.7
1531 | picocolors: 1.0.0
1532 | source-map-js: 1.0.2
1533 | optional: true
1534 |
1535 | postcss@8.4.47:
1536 | dependencies:
1537 | nanoid: 3.3.7
1538 | picocolors: 1.1.0
1539 | source-map-js: 1.2.1
1540 |
1541 | preact@10.13.2: {}
1542 |
1543 | property-information@6.5.0: {}
1544 |
1545 | regex@4.3.3: {}
1546 |
1547 | rfdc@1.4.1: {}
1548 |
1549 | rimraf@6.0.1:
1550 | dependencies:
1551 | glob: 11.0.0
1552 | package-json-from-dist: 1.0.1
1553 |
1554 | rollup@4.24.0:
1555 | dependencies:
1556 | '@types/estree': 1.0.6
1557 | optionalDependencies:
1558 | '@rollup/rollup-android-arm-eabi': 4.24.0
1559 | '@rollup/rollup-android-arm64': 4.24.0
1560 | '@rollup/rollup-darwin-arm64': 4.24.0
1561 | '@rollup/rollup-darwin-x64': 4.24.0
1562 | '@rollup/rollup-linux-arm-gnueabihf': 4.24.0
1563 | '@rollup/rollup-linux-arm-musleabihf': 4.24.0
1564 | '@rollup/rollup-linux-arm64-gnu': 4.24.0
1565 | '@rollup/rollup-linux-arm64-musl': 4.24.0
1566 | '@rollup/rollup-linux-powerpc64le-gnu': 4.24.0
1567 | '@rollup/rollup-linux-riscv64-gnu': 4.24.0
1568 | '@rollup/rollup-linux-s390x-gnu': 4.24.0
1569 | '@rollup/rollup-linux-x64-gnu': 4.24.0
1570 | '@rollup/rollup-linux-x64-musl': 4.24.0
1571 | '@rollup/rollup-win32-arm64-msvc': 4.24.0
1572 | '@rollup/rollup-win32-ia32-msvc': 4.24.0
1573 | '@rollup/rollup-win32-x64-msvc': 4.24.0
1574 | fsevents: 2.3.3
1575 |
1576 | search-insights@2.10.0: {}
1577 |
1578 | shebang-command@2.0.0:
1579 | dependencies:
1580 | shebang-regex: 3.0.0
1581 |
1582 | shebang-regex@3.0.0: {}
1583 |
1584 | shiki@1.21.0:
1585 | dependencies:
1586 | '@shikijs/core': 1.21.0
1587 | '@shikijs/engine-javascript': 1.21.0
1588 | '@shikijs/engine-oniguruma': 1.21.0
1589 | '@shikijs/types': 1.21.0
1590 | '@shikijs/vscode-textmate': 9.2.2
1591 | '@types/hast': 3.0.4
1592 |
1593 | signal-exit@4.1.0: {}
1594 |
1595 | source-map-js@1.0.2:
1596 | optional: true
1597 |
1598 | source-map-js@1.2.1: {}
1599 |
1600 | space-separated-tokens@2.0.2: {}
1601 |
1602 | speakingurl@14.0.1: {}
1603 |
1604 | string-width@4.2.3:
1605 | dependencies:
1606 | emoji-regex: 8.0.0
1607 | is-fullwidth-code-point: 3.0.0
1608 | strip-ansi: 6.0.1
1609 |
1610 | string-width@5.1.2:
1611 | dependencies:
1612 | eastasianwidth: 0.2.0
1613 | emoji-regex: 9.2.2
1614 | strip-ansi: 7.1.0
1615 |
1616 | stringify-entities@4.0.4:
1617 | dependencies:
1618 | character-entities-html4: 2.1.0
1619 | character-entities-legacy: 3.0.0
1620 |
1621 | strip-ansi@6.0.1:
1622 | dependencies:
1623 | ansi-regex: 5.0.1
1624 |
1625 | strip-ansi@7.1.0:
1626 | dependencies:
1627 | ansi-regex: 6.1.0
1628 |
1629 | superjson@2.2.1:
1630 | dependencies:
1631 | copy-anything: 3.0.5
1632 |
1633 | tabbable@6.2.0: {}
1634 |
1635 | to-fast-properties@2.0.0: {}
1636 |
1637 | trim-lines@3.0.1: {}
1638 |
1639 | unist-util-is@6.0.0:
1640 | dependencies:
1641 | '@types/unist': 3.0.3
1642 |
1643 | unist-util-position@5.0.0:
1644 | dependencies:
1645 | '@types/unist': 3.0.3
1646 |
1647 | unist-util-stringify-position@4.0.0:
1648 | dependencies:
1649 | '@types/unist': 3.0.3
1650 |
1651 | unist-util-visit-parents@6.0.1:
1652 | dependencies:
1653 | '@types/unist': 3.0.3
1654 | unist-util-is: 6.0.0
1655 |
1656 | unist-util-visit@5.0.0:
1657 | dependencies:
1658 | '@types/unist': 3.0.3
1659 | unist-util-is: 6.0.0
1660 | unist-util-visit-parents: 6.0.1
1661 |
1662 | vfile-message@4.0.2:
1663 | dependencies:
1664 | '@types/unist': 3.0.3
1665 | unist-util-stringify-position: 4.0.0
1666 |
1667 | vfile@6.0.3:
1668 | dependencies:
1669 | '@types/unist': 3.0.3
1670 | vfile-message: 4.0.2
1671 |
1672 | vite@5.4.8:
1673 | dependencies:
1674 | esbuild: 0.21.5
1675 | postcss: 8.4.47
1676 | rollup: 4.24.0
1677 | optionalDependencies:
1678 | fsevents: 2.3.3
1679 |
1680 | vitepress@1.3.4(@algolia/client-search@4.20.0)(postcss@8.4.33)(search-insights@2.10.0):
1681 | dependencies:
1682 | '@docsearch/css': 3.6.2
1683 | '@docsearch/js': 3.6.2(@algolia/client-search@4.20.0)(search-insights@2.10.0)
1684 | '@shikijs/core': 1.21.0
1685 | '@shikijs/transformers': 1.21.0
1686 | '@types/markdown-it': 14.1.2
1687 | '@vitejs/plugin-vue': 5.1.4(vite@5.4.8)(vue@3.5.11)
1688 | '@vue/devtools-api': 7.4.6
1689 | '@vue/shared': 3.5.11
1690 | '@vueuse/core': 11.1.0(vue@3.5.11)
1691 | '@vueuse/integrations': 11.1.0(focus-trap@7.5.4)(vue@3.5.11)
1692 | focus-trap: 7.5.4
1693 | mark.js: 8.11.1
1694 | minisearch: 7.1.0
1695 | shiki: 1.21.0
1696 | vite: 5.4.8
1697 | vue: 3.5.11
1698 | optionalDependencies:
1699 | postcss: 8.4.33
1700 | transitivePeerDependencies:
1701 | - '@algolia/client-search'
1702 | - '@types/node'
1703 | - '@types/react'
1704 | - '@vue/composition-api'
1705 | - async-validator
1706 | - axios
1707 | - change-case
1708 | - drauu
1709 | - fuse.js
1710 | - idb-keyval
1711 | - jwt-decode
1712 | - less
1713 | - lightningcss
1714 | - nprogress
1715 | - qrcode
1716 | - react
1717 | - react-dom
1718 | - sass
1719 | - sass-embedded
1720 | - search-insights
1721 | - sortablejs
1722 | - stylus
1723 | - sugarss
1724 | - terser
1725 | - typescript
1726 | - universal-cookie
1727 |
1728 | vue-demi@0.14.10(vue@3.5.11):
1729 | dependencies:
1730 | vue: 3.5.11
1731 |
1732 | vue@3.5.11:
1733 | dependencies:
1734 | '@vue/compiler-dom': 3.5.11
1735 | '@vue/compiler-sfc': 3.5.11
1736 | '@vue/runtime-dom': 3.5.11
1737 | '@vue/server-renderer': 3.5.11(vue@3.5.11)
1738 | '@vue/shared': 3.5.11
1739 |
1740 | which@2.0.2:
1741 | dependencies:
1742 | isexe: 2.0.0
1743 |
1744 | wrap-ansi@7.0.0:
1745 | dependencies:
1746 | ansi-styles: 4.3.0
1747 | string-width: 4.2.3
1748 | strip-ansi: 6.0.1
1749 |
1750 | wrap-ansi@8.1.0:
1751 | dependencies:
1752 | ansi-styles: 6.2.1
1753 | string-width: 5.1.2
1754 | strip-ansi: 7.1.0
1755 |
1756 | zwitch@2.0.4: {}
1757 |
--------------------------------------------------------------------------------