vira 31.28.3 → 31.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -36,9 +36,16 @@ export declare const ViraButton: import("element-vir").DeclarativeElementDefinit
36
36
  */
37
37
  color: ViraColorVariant | ViraThemeColorName;
38
38
  /**
39
- * Set to `true`
39
+ * Set to `true` to render `icon` after `text` instead of before it.
40
40
  *
41
41
  * @default false
42
42
  */
43
+ showIconOnRight: boolean;
44
+ /**
45
+ * Set to `true` to append a downwards chevron after the button's text.
46
+ *
47
+ * @deprecated Set `icon` to `ChevronDown16Icon` and `showIconOnRight` to `true` instead.
48
+ * @default false
49
+ */
43
50
  showMenuCaret: boolean;
44
51
  }>, {}, {}, "vira-button-with-menu-caret" | "vira-button-size-large" | "vira-button-size-medium" | "vira-button-size-small" | "vira-button-emphasis-standard" | "vira-button-emphasis-subtle" | "vira-button-color-red" | "vira-button-color-yellow" | "vira-button-color-green" | "vira-button-color-blue" | "vira-button-color-brand" | "vira-button-color-purple" | "vira-button-color-plain" | "vira-button-color-neutral" | "vira-button-color-teal" | "vira-button-color-pink" | "vira-button-color-grey" | "vira-button-disabled" | "vira-button-icon-only", "vira-button-text-color" | "vira-button-background-color" | "vira-button-border-color" | "vira-button-hover-text-color" | "vira-button-hover-background-color" | "vira-button-hover-border-color" | "vira-button-active-text-color" | "vira-button-active-background-color" | "vira-button-active-border-color" | "vira-button-disabled-text-color" | "vira-button-disabled-background-color" | "vira-button-disabled-border-color" | "vira-button-border-width" | "vira-button-border-radius", readonly [], readonly []>;
@@ -121,6 +121,7 @@ const neutralButtonColors = {
121
121
  export const ViraButton = defineViraElement()({
122
122
  tagName: 'vira-button',
123
123
  hostClasses: {
124
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
124
125
  'vira-button-with-menu-caret': ({ inputs }) => !!inputs.showMenuCaret,
125
126
  'vira-button-size-large': ({ inputs }) => inputs.buttonSize === ViraSize.Large,
126
127
  'vira-button-size-medium': ({ inputs }) => !inputs.buttonSize || inputs.buttonSize === ViraSize.Medium,
@@ -316,7 +317,8 @@ export const ViraButton = defineViraElement()({
316
317
  width: 0;
317
318
  }
318
319
 
319
- button ${ViraIcon} + .text-template {
320
+ button ${ViraIcon} + .text-template,
321
+ button .text-template + ${ViraIcon} {
320
322
  margin-left: 8px;
321
323
  }
322
324
 
@@ -375,6 +377,7 @@ export const ViraButton = defineViraElement()({
375
377
  : html `
376
378
  <span class="empty-text">&nbsp;</span>
377
379
  `;
380
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
378
381
  const caretIconTemplate = inputs.showMenuCaret
379
382
  ? html `
380
383
  <${ViraIcon.assign({
@@ -384,10 +387,18 @@ export const ViraButton = defineViraElement()({
384
387
  ></${ViraIcon}>
385
388
  `
386
389
  : nothing;
390
+ /* Both templates are interpolated with no whitespace between them so `+` selectors match. */
391
+ const templates = inputs.showIconOnRight
392
+ ? [
393
+ textTemplate,
394
+ iconTemplate,
395
+ ]
396
+ : [
397
+ iconTemplate,
398
+ textTemplate,
399
+ ];
387
400
  return html `
388
- <button ?disabled=${inputs.isDisabled}>
389
- ${iconTemplate}${textTemplate}${caretIconTemplate}
390
- </button>
401
+ <button ?disabled=${inputs.isDisabled}>${templates}${caretIconTemplate}</button>
391
402
  `;
392
403
  },
393
404
  });
@@ -11,6 +11,20 @@ export declare const ViraCollapsibleWrapper: import("element-vir").DeclarativeEl
11
11
  expandOnPrint?: boolean;
12
12
  }, {
13
13
  contentHeight: number;
14
+ contentWidth: number;
15
+ /**
16
+ * Collapsed content that is merely `height: 0` is still rendered, so the browser emits
17
+ * a line break for it when serializing a selection to plain text. Copying a region that
18
+ * spans collapsed wrappers then pastes with runs of blank lines. Taking the content out
19
+ * of layout entirely is what drops those breaks; `visibility: hidden` and `user-select:
20
+ * none` both leave them behind.
21
+ *
22
+ * This starts `false` even when collapsed because the wrapper takes both its width and
23
+ * its animation target height from the content, so the content has to be laid out once
24
+ * before it can be hidden.
25
+ */
26
+ isContentHidden: boolean;
27
+ collapsingElement: HTMLDivElement | undefined;
14
28
  }, {
15
29
  expandChange: import("element-vir").DefineEvent<boolean>;
16
30
  }, "vira-collapsible-wrapper-expand-on-print", `vira-${string}-`, readonly ["vira-collapsible-wrapper-header"], readonly []>;
@@ -1,4 +1,5 @@
1
- import { classMap, css, defineElementEvent, html, listen, onResize } from 'element-vir';
1
+ import { assertWrap } from '@augment-vir/assert';
2
+ import { classMap, css, defineElementEvent, html, listen, onDomCreated, onResize } from 'element-vir';
2
3
  import { noNativeFormStyles, noUserSelect, viraAnimationDurations } from '../styles/index.js';
3
4
  import { defineViraElement } from '../util/define-vira-element.js';
4
5
  /**
@@ -13,6 +14,20 @@ export const ViraCollapsibleWrapper = defineViraElement()({
13
14
  state() {
14
15
  return {
15
16
  contentHeight: 0,
17
+ contentWidth: 0,
18
+ /**
19
+ * Collapsed content that is merely `height: 0` is still rendered, so the browser emits
20
+ * a line break for it when serializing a selection to plain text. Copying a region that
21
+ * spans collapsed wrappers then pastes with runs of blank lines. Taking the content out
22
+ * of layout entirely is what drops those breaks; `visibility: hidden` and `user-select:
23
+ * none` both leave them behind.
24
+ *
25
+ * This starts `false` even when collapsed because the wrapper takes both its width and
26
+ * its animation target height from the content, so the content has to be laid out once
27
+ * before it can be hidden.
28
+ */
29
+ isContentHidden: false,
30
+ collapsingElement: undefined,
16
31
  };
17
32
  },
18
33
  hostClasses: {
@@ -48,12 +63,20 @@ export const ViraCollapsibleWrapper = defineViraElement()({
48
63
  }
49
64
  }
50
65
 
66
+ .content-wrapper.hidden-content {
67
+ display: none;
68
+ }
69
+
51
70
  @media print {
52
71
  :host(.${hostClasses['vira-collapsible-wrapper-expand-on-print'].name})
53
72
  .collapsing-element {
54
73
  height: auto !important;
55
74
  overflow: visible !important;
56
75
  transition: none !important;
76
+
77
+ & .content-wrapper.hidden-content {
78
+ display: flex !important;
79
+ }
57
80
  }
58
81
  }
59
82
  `,
@@ -61,12 +84,71 @@ export const ViraCollapsibleWrapper = defineViraElement()({
61
84
  expandChange: defineElementEvent(),
62
85
  },
63
86
  render({ state, slotNames, updateState, dispatch, events, inputs }) {
87
+ if (inputs.expanded && state.isContentHidden) {
88
+ updateState({
89
+ isContentHidden: false,
90
+ });
91
+ }
92
+ else if (!inputs.expanded &&
93
+ !state.isContentHidden &&
94
+ state.contentHeight &&
95
+ !state.collapsingElement?.clientHeight) {
96
+ /**
97
+ * Already at zero height, so no collapse animation will run and `transitionend` will
98
+ * never fire. Covers a wrapper that mounts collapsed and one that gets collapsed before
99
+ * its expanded height has been painted.
100
+ *
101
+ * Hiding here rather than straight from the resize callback: changing the size of the
102
+ * observed element from inside its own callback trips the browser's resize observer
103
+ * loop detection.
104
+ */
105
+ updateState({
106
+ isContentHidden: true,
107
+ });
108
+ }
109
+ /**
110
+ * Hidden content contributes no width, so the wrapper would shrink to its header without
111
+ * the width measured while the content was last laid out. `max-width` keeps that from
112
+ * blocking a later shrink to a narrower container.
113
+ */
114
+ const hiddenContentStyles = state.isContentHidden
115
+ ? css `
116
+ width: ${state.contentWidth}px;
117
+ max-width: 100%;
118
+ `
119
+ : css ``;
120
+ /**
121
+ * Hidden content is rendered without the resize observer rather than with a callback that
122
+ * ignores it. An attached observer still fires when the content is hidden, and the browser
123
+ * reports that as a resize observer loop.
124
+ */
125
+ const contentWrapperTemplate = state.isContentHidden
126
+ ? html `
127
+ <div class="content-wrapper hidden-content">
128
+ <slot></slot>
129
+ </div>
130
+ `
131
+ : html `
132
+ <div
133
+ ${onResize(({ contentRect }) => {
134
+ updateState({
135
+ contentHeight: contentRect.height,
136
+ contentWidth: contentRect.width,
137
+ });
138
+ })}
139
+ class="content-wrapper"
140
+ >
141
+ <slot></slot>
142
+ </div>
143
+ `;
64
144
  const collapsingStyles = inputs.expanded
65
145
  ? css `
66
146
  height: ${state.contentHeight}px;
147
+ ${hiddenContentStyles}
67
148
  `
68
149
  : css `
69
150
  height: 0;
151
+ ${hiddenContentStyles}
70
152
  `;
71
153
  return html `
72
154
  <button
@@ -84,17 +166,22 @@ export const ViraCollapsibleWrapper = defineViraElement()({
84
166
  })}"
85
167
  style=${collapsingStyles}
86
168
  disabled="disabled"
87
- >
88
- <div
89
- ${onResize(({ contentRect }) => {
169
+ ${onDomCreated((element) => {
90
170
  updateState({
91
- contentHeight: contentRect.height,
171
+ collapsingElement: assertWrap.instanceOf(element, HTMLDivElement),
92
172
  });
93
173
  })}
94
- class="content-wrapper"
95
- >
96
- <slot></slot>
97
- </div>
174
+ ${listen('transitionend', (event) => {
175
+ if (event.propertyName === 'height' &&
176
+ event.target === event.currentTarget &&
177
+ !inputs.expanded) {
178
+ updateState({
179
+ isContentHidden: true,
180
+ });
181
+ }
182
+ })}
183
+ >
184
+ ${contentWrapperTemplate}
98
185
  </div>
99
186
  `;
100
187
  },
@@ -270,6 +270,8 @@ export const ViraForm = defineViraElement()({
270
270
  min: field.min,
271
271
  max: field.max,
272
272
  timezone: field.timezone,
273
+ showDateOnly: field.showDateOnly,
274
+ showTimeOnly: field.showTimeOnly,
273
275
  isDisabled,
274
276
  hasError: field.hasError,
275
277
  isReadonly: inputs.isReadonly,
@@ -116,6 +116,10 @@ export type ViraFormField = ({
116
116
  max: FullDate;
117
117
  /** Timezone used to interpret the selected date. Defaults to the user's timezone. */
118
118
  timezone: string;
119
+ /** Only show the date part of the selected date when in readonly mode. */
120
+ showDateOnly: boolean;
121
+ /** Only show the time part of the selected date when in readonly mode. */
122
+ showTimeOnly: boolean;
119
123
  }> & CommonViraFormFields);
120
124
  /**
121
125
  * A collection of form fields for `ViraForm`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vira",
3
- "version": "31.28.3",
3
+ "version": "31.30.0",
4
4
  "description": "A simple and highly versatile design system using element-vir.",
5
5
  "keywords": [
6
6
  "design",