vira 31.22.2 → 31.23.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.
@@ -18,6 +18,10 @@ export type ViraCheckboxInputs = {
18
18
  stylePassthrough: Partial<Record<ViraCheckboxInnerElements, CSSResult>>;
19
19
  attributePassthrough: Partial<Record<ViraCheckboxInnerElements, AttributeValues>>;
20
20
  isDisabled: boolean;
21
+ /**
22
+ * Text label for the checkbox. Used as the fallback when the `vira-checkbox-label` slot is not
23
+ * filled.
24
+ */
21
25
  label: string;
22
26
  hasError: boolean;
23
27
  useHorizontalLabel: boolean;
@@ -33,6 +37,8 @@ export type ViraCheckboxInputs = {
33
37
  * @category Elements
34
38
  * @see https://electrovir.github.io/vira/book/elements/vira-checkbox
35
39
  */
36
- export declare const ViraCheckbox: import("element-vir").DeclarativeElementDefinition<"vira-checkbox", Readonly<ViraCheckboxInputs>, {}, {
40
+ export declare const ViraCheckbox: import("element-vir").DeclarativeElementDefinition<`vira-${string}`, Readonly<ViraCheckboxInputs>, {
41
+ hasSlottedLabel: boolean;
42
+ }, {
37
43
  valueChange: import("element-vir").DefineEvent<boolean>;
38
- }, "vira-checkbox-horizontal" | "vira-checkbox-filled-checked" | "vira-checkbox-filled-unchecked", "vira-checkbox-", readonly [], readonly []>;
44
+ }, "vira-checkbox-horizontal" | "vira-checkbox-filled-checked" | "vira-checkbox-filled-unchecked", `vira-${string}-`, readonly ["vira-checkbox-label"], readonly []>;
@@ -1,4 +1,5 @@
1
- import { attributes, classMap, css, defineElementEvent, html, ifDefined, listen, listenToActivate, nothing, } from 'element-vir';
1
+ import { extractEventTarget } from '@augment-vir/web';
2
+ import { attributes, classMap, css, defineElementEvent, html, ifDefined, listen, listenToActivate, } from 'element-vir';
2
3
  import { Check24Icon, viraIconCssVars } from '../icons/index.js';
3
4
  import { viraDisabledStyles } from '../styles/disabled.js';
4
5
  import { createFocusStyles } from '../styles/focus.js';
@@ -14,6 +15,14 @@ import { ViraIcon } from './vira-icon.element.js';
14
15
  */
15
16
  export const ViraCheckbox = defineViraElement()({
16
17
  tagName: 'vira-checkbox',
18
+ slotNames: [
19
+ 'vira-checkbox-label',
20
+ ],
21
+ state() {
22
+ return {
23
+ hasSlottedLabel: false,
24
+ };
25
+ },
17
26
  hostClasses: {
18
27
  'vira-checkbox-horizontal': ({ inputs }) => !!inputs.useHorizontalLabel,
19
28
  'vira-checkbox-filled-checked': ({ inputs }) => !!inputs.fillWhenChecked,
@@ -86,6 +95,10 @@ export const ViraCheckbox = defineViraElement()({
86
95
  & .label-text {
87
96
  cursor: pointer;
88
97
  font-weight: ${viraFormCssVars['vira-form-label-font-weight'].value};
98
+
99
+ &.empty {
100
+ display: none;
101
+ }
89
102
  }
90
103
 
91
104
  &:not(.disabled):hover .custom-checkbox {
@@ -126,7 +139,7 @@ export const ViraCheckbox = defineViraElement()({
126
139
  }
127
140
 
128
141
  ${hostClasses['vira-checkbox-horizontal'].selector} label {
129
- flex-direction: row;
142
+ flex-direction: row-reverse;
130
143
  align-items: center;
131
144
  gap: 8px;
132
145
 
@@ -138,23 +151,34 @@ export const ViraCheckbox = defineViraElement()({
138
151
  events: {
139
152
  valueChange: defineElementEvent(),
140
153
  },
141
- render({ inputs, dispatch, events }) {
154
+ render({ inputs, dispatch, events, slotNames, state, updateState }) {
142
155
  function updateValue() {
143
156
  if (!inputs.isDisabled) {
144
157
  dispatch(new events.valueChange(!inputs.value));
145
158
  }
146
159
  }
147
- const textLabel = inputs.label
148
- ? html `
149
- <span
150
- class="label-text"
151
- ${attributes(inputs.attributePassthrough?.['text'])}
152
- style=${ifDefined(inputs.stylePassthrough?.['text'])}
153
- >
154
- ${inputs.label}
155
- </span>
156
- `
157
- : nothing;
160
+ const hasLabel = !!inputs.label || state.hasSlottedLabel;
161
+ const textLabel = html `
162
+ <span
163
+ class="label-text ${classMap({
164
+ empty: !hasLabel,
165
+ })}"
166
+ ${attributes(inputs.attributePassthrough?.['text'])}
167
+ style=${ifDefined(inputs.stylePassthrough?.['text'])}
168
+ >
169
+ <slot
170
+ name=${slotNames['vira-checkbox-label']}
171
+ ${listen('slotchange', (event) => {
172
+ const slotElement = extractEventTarget(event, HTMLSlotElement);
173
+ updateState({
174
+ hasSlottedLabel: !!slotElement.assignedNodes().length,
175
+ });
176
+ })}
177
+ >
178
+ ${inputs.label}
179
+ </slot>
180
+ </span>
181
+ `;
158
182
  return html `
159
183
  <label
160
184
  class=${classMap({
@@ -103,20 +103,19 @@ export const ViraForm = defineViraElement()({
103
103
  }
104
104
  }
105
105
  const formFieldTemplates = getObjectTypedEntries(inputs.fields).map(([key, field,]) => {
106
- const label = applyRequiredLabel(field.label, !!field.isRequired && !inputs.hideRequiredMarkers);
107
106
  const isDisabled = !!(inputs.isDisabled || field.isDisabled);
108
- const childLabel = inputs.useHorizontalLabels ? undefined : label;
109
- const horizontalLabelAttributes = inputs.useHorizontalLabels && label
110
- ? {
111
- 'aria-label': label,
112
- }
113
- : {};
107
+ const showRequiredMarker = !!field.isRequired && !inputs.hideRequiredMarkers;
114
108
  if (field.isHidden) {
115
109
  return nothing;
116
110
  }
117
111
  else if (field.type === ViraFormFieldType.Checkbox) {
112
+ const checkboxLabel = showRequiredMarker
113
+ ? html `
114
+ ${field.label}*
115
+ `
116
+ : field.label;
118
117
  return wrapFormField({
119
- label,
118
+ label: checkboxLabel,
120
119
  fieldTemplate: html `
121
120
  <${ViraCheckbox.assign({
122
121
  value: field.value || false,
@@ -125,14 +124,6 @@ export const ViraForm = defineViraElement()({
125
124
  useHorizontalLabel: inputs.horizontalCheckboxes,
126
125
  fillWhenChecked: field.fillWhenChecked,
127
126
  fillWhenUnchecked: field.fillWhenUnchecked,
128
- label: childLabel,
129
- ...(inputs.useHorizontalLabels && label
130
- ? {
131
- attributePassthrough: {
132
- 'custom-checkbox': horizontalLabelAttributes,
133
- },
134
- }
135
- : {}),
136
127
  })}
137
128
  ${field.testId ? testId(field.testId) : nothing}
138
129
  ${listen(ViraCheckbox.events.valueChange, (event) => {
@@ -142,11 +133,28 @@ export const ViraForm = defineViraElement()({
142
133
  value: event.detail,
143
134
  }));
144
135
  })}
145
- ></${ViraCheckbox}>
136
+ >
137
+ ${inputs.useHorizontalLabels
138
+ ? nothing
139
+ : html `
140
+ <span
141
+ slot=${ViraCheckbox.slotNames['vira-checkbox-label']}
142
+ >
143
+ ${checkboxLabel}
144
+ </span>
145
+ `}
146
+ </${ViraCheckbox}>
146
147
  `,
147
148
  });
148
149
  }
149
- else if (field.type === ViraFormFieldType.Select) {
150
+ const label = applyRequiredLabel(field.label, showRequiredMarker);
151
+ const childLabel = inputs.useHorizontalLabels ? undefined : label;
152
+ const horizontalLabelAttributes = inputs.useHorizontalLabels && label
153
+ ? {
154
+ 'aria-label': label,
155
+ }
156
+ : {};
157
+ if (field.type === ViraFormFieldType.Select) {
150
158
  return wrapFormField({
151
159
  label,
152
160
  fieldTemplate: html `
@@ -1,5 +1,6 @@
1
1
  import { type PartialWithUndefined } from '@augment-vir/common';
2
2
  import { type FullDate } from 'date-vir';
3
+ import { type HtmlInterpolation } from 'element-vir';
3
4
  import { type ViraIconSvg } from '../icons/icon-svg.js';
4
5
  import { type ViraSelectOption } from './vira-select-option.js';
5
6
  /**
@@ -79,12 +80,17 @@ export type ViraFormField = ({
79
80
  }> & CommonViraFormFields) | ({
80
81
  type: ViraFormFieldType.Checkbox;
81
82
  value: boolean | undefined;
83
+ /**
84
+ * Label for the checkbox. Unlike other field types, this accepts arbitrary HTML so the
85
+ * checkbox's label slot can be filled with rich content.
86
+ */
87
+ label: HtmlInterpolation;
82
88
  } & PartialWithUndefined<{
83
89
  /** The checkbox will be filled with a form selection color when it is checked. */
84
90
  fillWhenChecked: boolean;
85
91
  /** The checkbox will be filled with a form error color when it is unchecked. */
86
92
  fillWhenUnchecked: boolean;
87
- }> & CommonViraFormFields) | ({
93
+ }> & Omit<CommonViraFormFields, 'label'>) | ({
88
94
  type: ViraFormFieldType.Number;
89
95
  value: number | undefined;
90
96
  } & PartialWithUndefined<{
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vira",
3
- "version": "31.22.2",
3
+ "version": "31.23.0",
4
4
  "description": "A simple and highly versatile design system using element-vir.",
5
5
  "keywords": [
6
6
  "design",