@redseed/redseed-ui-vue3 10.3.2 → 10.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redseed/redseed-ui-vue3",
3
- "version": "10.3.2",
3
+ "version": "10.3.3",
4
4
  "description": "RedSeed UI Vue 3 components",
5
5
  "main": "index.js",
6
6
  "repository": "https://github.com/redseedtraining/redseed-ui",
@@ -1,7 +1,8 @@
1
1
  <script setup>
2
- import { ref, computed, watch, watchEffect, useSlots, Comment, Fragment } from 'vue'
2
+ import { ref, computed, watch, watchEffect, useSlots } from 'vue'
3
3
  import Icon from '../Icon/Icon.vue'
4
4
  import { XMarkIcon } from '@heroicons/vue/24/outline'
5
+ import { rendersContent } from '../../helpers/slots'
5
6
 
6
7
  const props = defineProps({
7
8
  closed: {
@@ -81,40 +82,6 @@ watch(() => props.closed, (value) => {
81
82
  isClosed.value = value
82
83
  })
83
84
 
84
- /**
85
- * A Fragment is a wrapper, so its own presence answers nothing — only what is
86
- * inside it does. Hence the recursion: a `v-for` compiles to a Fragment and
87
- * leaves a comment placeholder for each hidden item, so counting children
88
- * reported content for a list whose every action was filtered out (the usual
89
- * shape for permission-gated actions), and a nested `<template>` puts another
90
- * Fragment inside that one.
91
- *
92
- * `Array.isArray` rather than recursing straight into `children`, which is a raw
93
- * string on a Fragment built by hand as `h(Fragment, null, 'text')`. Vue's own
94
- * `ensureValidVNode` assumes the array and throws on that shape, so answering
95
- * "renders" here only hands it a slot it cannot render; treating it as empty
96
- * drops the row instead, which is the quieter of the two failures. Compiled
97
- * templates always produce the array.
98
- */
99
- function rendersNode(node) {
100
- if (node.type === Comment) return false
101
- if (node.type === Fragment) return Array.isArray(node.children) && node.children.some(rendersNode)
102
-
103
- return true
104
- }
105
-
106
- /**
107
- * Whether a slot renders anything at all. Slot *presence* is not the same
108
- * question: a slot holding only a falsy `v-if` is still a truthy slot function
109
- * that renders a comment placeholder, which would put an empty padded row under
110
- * the message.
111
- */
112
- function rendersContent(slot) {
113
- const nodes = slot?.()
114
-
115
- return Boolean(nodes) && nodes.some(rendersNode)
116
- }
117
-
118
85
  /**
119
86
  * Announce the box as a live region so flash / MOTD content reaches assistive
120
87
  * tech (WCAG 4.1.3 Status Messages). `alert` is assertive — reserved for errors
@@ -195,7 +162,15 @@ function close() {
195
162
  text on a coloured tint is a contrast problem, and the action is a way
196
163
  out of the message rather than a restatement of its severity.
197
164
  -->
198
- <div v-if="hasDismiss || rendersContent($slots.actions)" class="rsui-message-box__actions">
165
+ <!--
166
+ The scope is forwarded, and that is the whole of #331. `#actions` is declared
167
+ scoped below — `<slot name="actions" :close="close">` — so a consumer writing
168
+ the documented `<template #actions="{ close }">` compiles to a function that
169
+ destructures its only parameter. Probing it bare passed `undefined` and threw
170
+ `Cannot destructure property 'close' of 'undefined'`, taking the whole
171
+ MessageBox down. Shipped in 8.66.0.
172
+ -->
173
+ <div v-if="hasDismiss || rendersContent($slots.actions, { close })" class="rsui-message-box__actions">
199
174
  <button v-if="hasDismiss"
200
175
  type="button"
201
176
  class="rsui-message-box__dismiss"
@@ -52,7 +52,15 @@ export function rendersContent(slot, scope) {
52
52
  * Comment vnodes are what a falsy `v-if` leaves behind. Fragments wrap lists and
53
53
  * `<template v-if>` blocks, so a truthy wrapper around a falsy child is a
54
54
  * Fragment whose only child is a Comment — counting length would treat that as
55
- * content.
55
+ * content. A `v-for` over a filtered list is the usual shape, and a nested
56
+ * `<template>` puts another Fragment inside that one.
57
+ *
58
+ * `Array.isArray` rather than recursing straight into `children`, which is a raw
59
+ * string on a Fragment built by hand as `h(Fragment, null, 'text')`. Vue's own
60
+ * `ensureValidVNode` assumes the array and throws on that shape, so answering
61
+ * "renders" there only hands it a slot it cannot render; treating it as empty
62
+ * drops the region instead, which is the quieter of the two failures. Compiled
63
+ * templates always produce the array.
56
64
  */
57
65
  function rendersNode(node) {
58
66
  if (node.type === Comment) return false