vira 26.5.8 → 26.6.1

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.
@@ -8,6 +8,7 @@ export * from './pop-up/vira-pop-up-menu.element.js';
8
8
  export * from './pop-up/vira-pop-up-trigger.element.js';
9
9
  export * from './vira-bold-text.element.js';
10
10
  export * from './vira-button.element.js';
11
+ export * from './vira-checkbox.element.js';
11
12
  export * from './vira-collapsible-wrapper.element.js';
12
13
  export * from './vira-dropdown.element.js';
13
14
  export * from './vira-icon.element.js';
@@ -8,6 +8,7 @@ export * from './pop-up/vira-pop-up-menu.element.js';
8
8
  export * from './pop-up/vira-pop-up-trigger.element.js';
9
9
  export * from './vira-bold-text.element.js';
10
10
  export * from './vira-button.element.js';
11
+ export * from './vira-checkbox.element.js';
11
12
  export * from './vira-collapsible-wrapper.element.js';
12
13
  export * from './vira-dropdown.element.js';
13
14
  export * from './vira-icon.element.js';
@@ -1,7 +1,7 @@
1
1
  import { check } from '@augment-vir/assert';
2
2
  import { nav, navAttribute, NavController, NavValue } from 'device-navigation';
3
3
  import { classMap, css, html, ifDefined, testId } from 'element-vir';
4
- import { viraFormCssVars } from '../../styles/form-themes.js';
4
+ import { viraFormCssVars } from '../../styles/form-styles.js';
5
5
  import { noNativeFormStyles, viraDisabledStyles } from '../../styles/index.js';
6
6
  import { defineViraElement } from '../define-vira-element.js';
7
7
  import { ViraLink } from '../vira-link.element.js';
@@ -1,6 +1,6 @@
1
1
  import { css, html } from 'element-vir';
2
2
  import { viraBorders } from '../../styles/border.js';
3
- import { viraFormCssVars } from '../../styles/form-themes.js';
3
+ import { viraFormCssVars } from '../../styles/form-styles.js';
4
4
  import { viraShadows } from '../../styles/shadows.js';
5
5
  import { defineViraElement } from '../define-vira-element.js';
6
6
  /**
@@ -67,15 +67,13 @@ export const ViraPopUpTrigger = defineViraElement()({
67
67
  cursor: pointer;
68
68
  max-width: 100%;
69
69
  position: relative;
70
- outline: none;
71
70
  flex-grow: 1;
72
71
  box-sizing: border-box;
73
- }
74
72
 
75
- ${createFocusStyles({
76
- selector: '.dropdown-wrapper:focus',
73
+ ${createFocusStyles({
77
74
  elementBorderSize: 1,
78
75
  })}
76
+ }
79
77
 
80
78
  .dropdown-trigger {
81
79
  box-sizing: border-box;
@@ -82,7 +82,6 @@ export const ViraButton = defineViraElement()({
82
82
  position: relative;
83
83
  width: 100%;
84
84
  height: 100%;
85
- outline: none;
86
85
  border: 2px solid transparent;
87
86
  box-sizing: border-box;
88
87
  display: inline-flex;
@@ -97,17 +96,16 @@ export const ViraButton = defineViraElement()({
97
96
  background-color
98
97
  ${viraAnimationDurations['vira-interaction-animation-duration'].value},
99
98
  border-color ${viraAnimationDurations['vira-interaction-animation-duration'].value};
99
+
100
+ ${createFocusStyles({
101
+ elementBorderSize: 2,
102
+ })}
100
103
  }
101
104
 
102
105
  .empty-text {
103
106
  width: 0;
104
107
  }
105
108
 
106
- ${createFocusStyles({
107
- selector: 'button:focus:focus-visible:not(:active):not([disabled])',
108
- elementBorderSize: 2,
109
- })}
110
-
111
109
  button ${ViraIcon} + .text-template {
112
110
  margin-left: 8px;
113
111
  }
@@ -0,0 +1,31 @@
1
+ import { type PartialWithUndefined } from '@augment-vir/common';
2
+ import { type AttributeValues, type CSSResult } from 'element-vir';
3
+ import { ViraIcon } from './vira-icon.element.js';
4
+ /**
5
+ * All inner elements supported by {@link ViraCheckbox}.
6
+ *
7
+ * @category Internals
8
+ */
9
+ export type ViraCheckboxInnerElements = 'label' | 'custom-checkbox' | typeof ViraIcon.tagName;
10
+ /**
11
+ * Inputs for {@link ViraCheckbox}.
12
+ *
13
+ * @category Internal
14
+ */
15
+ export type ViraCheckboxInputs = PartialWithUndefined<{
16
+ stylePassthrough: Record<ViraCheckboxInnerElements, CSSResult>;
17
+ attributePassthrough: Record<ViraCheckboxInnerElements, AttributeValues>;
18
+ disabled: boolean;
19
+ }> & {
20
+ value: boolean;
21
+ };
22
+ /**
23
+ * A custom checkbox.
24
+ *
25
+ * @category Input
26
+ * @category Elements
27
+ * @see https://electrovir.github.io/element-vir/vira/book/elements/vira-checkbox
28
+ */
29
+ export declare const ViraCheckbox: import("element-vir").DeclarativeElementDefinition<"vira-checkbox", Readonly<ViraCheckboxInputs>, {}, {
30
+ valueChange: import("element-vir").DefineEvent<boolean>;
31
+ }, "vira-checkbox-", "vira-checkbox-", readonly []>;
@@ -0,0 +1,117 @@
1
+ import { attributes, classMap, css, defineElementEvent, html, ifDefined, listen, listenToActivate, } from 'element-vir';
2
+ import { Check24Icon, viraIconCssVars } from '../icons/index.js';
3
+ import { viraBorders } from '../styles/border.js';
4
+ import { viraDisabledStyles } from '../styles/disabled.js';
5
+ import { createFocusStyles } from '../styles/focus.js';
6
+ import { viraFormCssVars } from '../styles/form-styles.js';
7
+ import { defineViraElement } from './define-vira-element.js';
8
+ import { ViraIcon } from './vira-icon.element.js';
9
+ /**
10
+ * A custom checkbox.
11
+ *
12
+ * @category Input
13
+ * @category Elements
14
+ * @see https://electrovir.github.io/element-vir/vira/book/elements/vira-checkbox
15
+ */
16
+ export const ViraCheckbox = defineViraElement()({
17
+ tagName: 'vira-checkbox',
18
+ styles: css `
19
+ :host {
20
+ height: 24px;
21
+ aspect-ratio: 1;
22
+ display: inline-flex;
23
+ }
24
+
25
+ label,
26
+ ${ViraIcon}, .custom-checkbox {
27
+ height: 100%;
28
+ width: 100%;
29
+ box-sizing: border-box;
30
+ }
31
+
32
+ label {
33
+ &.disabled {
34
+ cursor: not-allowed;
35
+ }
36
+ }
37
+
38
+ ${ViraIcon} {
39
+ ${viraIconCssVars['vira-icon-stroke-width'].name}: 3px;
40
+ opacity: 0;
41
+ }
42
+
43
+ /* The visible custom box */
44
+ .custom-checkbox {
45
+ border: 1px solid ${viraFormCssVars['vira-form-border-color'].value};
46
+ color: ${viraFormCssVars['vira-form-foreground-color'].value};
47
+ border-radius: ${viraBorders['vira-form-input-radius'].value};
48
+ display: inline-block;
49
+ position: relative;
50
+ cursor: pointer;
51
+
52
+ ${createFocusStyles({ elementBorderSize: 1 })}
53
+
54
+ &.checked {
55
+ & ${ViraIcon} {
56
+ opacity: 1;
57
+ }
58
+ }
59
+
60
+ &:hover {
61
+ background-color: ${viraFormCssVars['vira-form-selection-hover-background-color']
62
+ .value};
63
+ }
64
+
65
+ &:active {
66
+ background-color: ${viraFormCssVars['vira-form-selection-active-background-color']
67
+ .value};
68
+ }
69
+
70
+ &.disabled {
71
+ ${viraDisabledStyles};
72
+ }
73
+ }
74
+ `,
75
+ events: {
76
+ valueChange: defineElementEvent(),
77
+ },
78
+ render({ inputs, dispatch, events }) {
79
+ function updateValue() {
80
+ if (!inputs.disabled) {
81
+ dispatch(new events.valueChange(!inputs.value));
82
+ }
83
+ }
84
+ return html `
85
+ <label
86
+ class=${classMap({
87
+ disabled: !!inputs.disabled,
88
+ })}
89
+ ${attributes(inputs.attributePassthrough?.label)}
90
+ style=${ifDefined(inputs.stylePassthrough?.label)}
91
+ >
92
+ <span
93
+ class="custom-checkbox ${classMap({
94
+ checked: inputs.value,
95
+ disabled: !!inputs.disabled,
96
+ })}"
97
+ role="checkbox"
98
+ aria-checked=${inputs.value ? 'true' : 'false'}
99
+ aria-disabled=${inputs.disabled ? 'true' : 'false'}
100
+ tabindex=${inputs.disabled ? '-1' : '0'}
101
+ ${attributes(inputs.attributePassthrough?.['custom-checkbox'])}
102
+ style=${ifDefined(inputs.stylePassthrough?.['custom-checkbox'])}
103
+ ${listenToActivate(updateValue)}
104
+ ${listen('click', updateValue)}
105
+ >
106
+ <${ViraIcon.assign({
107
+ icon: Check24Icon,
108
+ fitContainer: true,
109
+ })}
110
+ ${attributes(inputs.attributePassthrough?.[ViraIcon.tagName])}
111
+ style=${ifDefined(inputs.stylePassthrough?.[ViraIcon.tagName])}
112
+ ></${ViraIcon}>
113
+ </span>
114
+ </label>
115
+ `;
116
+ },
117
+ });
@@ -3,7 +3,7 @@ import { filterMap } from '@augment-vir/common';
3
3
  import { classMap, css, defineElementEvent, html, ifDefined, listen, nothing, testId, } from 'element-vir';
4
4
  import { ChevronUp24Icon } from '../icons/index.js';
5
5
  import { viraBorders } from '../styles/border.js';
6
- import { viraFormCssVars } from '../styles/form-themes.js';
6
+ import { viraFormCssVars } from '../styles/form-styles.js';
7
7
  import { noUserSelect, viraAnimationDurations } from '../styles/index.js';
8
8
  import { defineViraElement } from './define-vira-element.js';
9
9
  import { ViraMenuTrigger } from './pop-up/vira-menu-trigger.element.js';
@@ -4,7 +4,7 @@ export * from './shared-text-input-logic.js';
4
4
  /**
5
5
  * Input types for {@link ViraInput}.
6
6
  *
7
- * @category Input
7
+ * @category Internal
8
8
  */
9
9
  export declare enum ViraInputType {
10
10
  Default = "text",
@@ -12,7 +12,7 @@ export * from './shared-text-input-logic.js';
12
12
  /**
13
13
  * Input types for {@link ViraInput}.
14
14
  *
15
- * @category Input
15
+ * @category Internal
16
16
  */
17
17
  export var ViraInputType;
18
18
  (function (ViraInputType) {
@@ -149,11 +149,6 @@ export const ViraInput = defineViraElement()({
149
149
  cursor: text;
150
150
  }
151
151
 
152
- ${createFocusStyles({
153
- selector: 'input:focus:focus-visible:not(:active):not([disabled]) ~ .focus-border',
154
- elementBorderSize: 0,
155
- })}
156
-
157
152
  .left-side-icon {
158
153
  margin-right: calc(${cssVars['vira-input-padding-horizontal'].value} - 4px);
159
154
  }
@@ -169,6 +164,14 @@ export const ViraInput = defineViraElement()({
169
164
  text-overflow: ellipsis;
170
165
  box-sizing: border-box;
171
166
  overflow: hidden;
167
+ outline: none;
168
+
169
+ &:focus:focus-visible:not(:active):not([disabled]) ~ .focus-border {
170
+ ${createFocusStyles({
171
+ elementBorderSize: 0,
172
+ noNesting: true,
173
+ })}
174
+ }
172
175
  }
173
176
 
174
177
  ::selection {
@@ -185,10 +188,6 @@ export const ViraInput = defineViraElement()({
185
188
  overflow: hidden;
186
189
  }
187
190
 
188
- input:focus {
189
- outline: none;
190
- }
191
-
192
191
  input::placeholder {
193
192
  color: ${cssVars['vira-input-placeholder-color'].value};
194
193
  }
@@ -321,9 +320,7 @@ export const ViraInput = defineViraElement()({
321
320
  });
322
321
  })}
323
322
  placeholder=${ifDefined(inputs.placeholder || undefined)}
324
- ${inputs.attributePassthrough
325
- ? attributes(inputs.attributePassthrough)
326
- : nothing}
323
+ ${attributes(inputs.attributePassthrough)}
327
324
  />
328
325
  ${renderIf(!!(inputs.showClearButton && inputs.value), html `
329
326
  <button
@@ -1,4 +1,4 @@
1
- import { attributes, css, html, ifDefined, listen, nothing, } from 'element-vir';
1
+ import { attributes, css, html, ifDefined, listen, } from 'element-vir';
2
2
  import { defineViraElement } from './define-vira-element.js';
3
3
  /**
4
4
  * A hyperlink wrapper element that can be configured to emit route change events rather than just
@@ -57,9 +57,7 @@ export const ViraLink = defineViraElement()({
57
57
  href=${inputs.link.url}
58
58
  target="_blank"
59
59
  rel="noopener noreferrer"
60
- ${inputs.attributePassthrough?.a
61
- ? attributes(inputs.attributePassthrough.a)
62
- : nothing}
60
+ ${attributes(inputs.attributePassthrough?.a)}
63
61
  style=${ifDefined(inputs.stylePassthrough?.a)}
64
62
  >
65
63
  <slot></slot>
@@ -75,9 +73,7 @@ export const ViraLink = defineViraElement()({
75
73
  <a
76
74
  href=${linkUrl}
77
75
  rel="noopener noreferrer"
78
- ${inputs.attributePassthrough?.a
79
- ? attributes(inputs.attributePassthrough.a)
80
- : nothing}
76
+ ${attributes(inputs.attributePassthrough?.a)}
81
77
  style=${ifDefined(inputs.stylePassthrough?.a)}
82
78
  ${listen('click', clickCallback)}
83
79
  >
@@ -1,3 +1,4 @@
1
+ import { type PartialWithUndefined } from '@augment-vir/common';
1
2
  /**
2
3
  * CSS vars for Vira focus colors.
3
4
  *
@@ -16,14 +17,15 @@ export declare const viraFocusCssVars: import("lit-css-vars").CssVarDefinitions<
16
17
  *
17
18
  * @category Styles
18
19
  */
19
- export declare function createFocusStyles({ selector, elementBorderSize, outlineGap, outlineWidth, }: {
20
- selector: string;
20
+ export declare function createFocusStyles({ elementBorderSize, outlineGap, outlineWidth, noNesting, }: {
21
21
  /**
22
22
  * ElementBorderSize here is used to fix the outline when the element these styles are attached
23
23
  * to has a border. The dev must specify that border size here for the offsets to be calculated
24
24
  * correctly.
25
25
  */
26
26
  elementBorderSize: number;
27
- outlineGap?: number;
28
- outlineWidth?: number;
29
- }): import("element-vir").CSSResult;
27
+ } & PartialWithUndefined<{
28
+ outlineGap: number;
29
+ outlineWidth: number;
30
+ noNesting: boolean;
31
+ }>): import("element-vir").CSSResult;
@@ -20,21 +20,33 @@ export const viraFocusCssVars = defineCssVars({
20
20
  *
21
21
  * @category Styles
22
22
  */
23
- export function createFocusStyles({ selector, elementBorderSize, outlineGap = 2, outlineWidth = 2, }) {
23
+ export function createFocusStyles({ elementBorderSize, outlineGap = 2, outlineWidth = 2, noNesting, }) {
24
24
  const outlineSpacing = unsafeCSS(addPx(outlineWidth + outlineGap + elementBorderSize));
25
+ const styles = css `
26
+ content: '';
27
+ top: calc(${outlineSpacing} * -1);
28
+ left: calc(${outlineSpacing} * -1);
29
+ position: absolute;
30
+ width: calc(100% + calc(${outlineSpacing} * 2));
31
+ height: calc(100% + calc(${outlineSpacing} * 2));
32
+ box-sizing: border-box;
33
+ pointer-events: none;
34
+ border: ${outlineWidth}px solid ${viraFocusCssVars['vira-focus-outline-color'].value};
35
+ border-radius: ${viraFocusCssVars['vira-focus-outline-border-radius'].value};
36
+ z-index: 100;
37
+ `;
38
+ if (noNesting) {
39
+ return styles;
40
+ }
25
41
  return css `
26
- ${unsafeCSS(selector)}::after {
27
- content: '';
28
- top: calc(${outlineSpacing} * -1);
29
- left: calc(${outlineSpacing} * -1);
30
- position: absolute;
31
- width: calc(100% + calc(${outlineSpacing} * 2));
32
- height: calc(100% + calc(${outlineSpacing} * 2));
33
- box-sizing: border-box;
34
- pointer-events: none;
35
- border: ${outlineWidth}px solid ${viraFocusCssVars['vira-focus-outline-color'].value};
36
- border-radius: ${viraFocusCssVars['vira-focus-outline-border-radius'].value};
37
- z-index: 100;
42
+ outline: none;
43
+
44
+ &:focus {
45
+ outline: none;
46
+ }
47
+
48
+ &:focus:focus-visible:not(:active):not([disabled])::after {
49
+ ${styles}
38
50
  }
39
51
  `;
40
52
  }
@@ -4,7 +4,7 @@ export * from './color.js';
4
4
  export * from './disabled.js';
5
5
  export * from './durations.js';
6
6
  export * from './focus.js';
7
- export * from './form-themes.js';
7
+ export * from './form-styles.js';
8
8
  export * from './native-styles.js';
9
9
  export * from './scrollbar.js';
10
10
  export * from './shadows.js';
@@ -4,7 +4,7 @@ export * from './color.js';
4
4
  export * from './disabled.js';
5
5
  export * from './durations.js';
6
6
  export * from './focus.js';
7
- export * from './form-themes.js';
7
+ export * from './form-styles.js';
8
8
  export * from './native-styles.js';
9
9
  export * from './scrollbar.js';
10
10
  export * from './shadows.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vira",
3
- "version": "26.5.8",
3
+ "version": "26.6.1",
4
4
  "description": "A simple and highly versatile design system using element-vir.",
5
5
  "keywords": [
6
6
  "design",
@@ -38,36 +38,36 @@
38
38
  "test:docs": "virmator docs check"
39
39
  },
40
40
  "dependencies": {
41
- "@augment-vir/assert": "^31.26.0",
42
- "@augment-vir/common": "^31.26.0",
43
- "@augment-vir/web": "^31.26.0",
41
+ "@augment-vir/assert": "^31.28.0",
42
+ "@augment-vir/common": "^31.28.0",
43
+ "@augment-vir/web": "^31.28.0",
44
44
  "colorjs.io": "^0.5.2",
45
- "date-vir": "^7.3.2",
45
+ "date-vir": "^7.4.0",
46
46
  "device-navigation": "^4.5.5",
47
47
  "lit-css-vars": "^3.0.11",
48
48
  "observavir": "^2.1.0",
49
49
  "page-active": "^1.0.1",
50
- "spa-router-vir": "^6.1.3",
50
+ "spa-router-vir": "^6.2.0",
51
51
  "type-fest": "^4.41.0",
52
52
  "typed-event-target": "^4.1.0"
53
53
  },
54
54
  "devDependencies": {
55
- "@augment-vir/test": "^31.26.0",
55
+ "@augment-vir/test": "^31.28.0",
56
56
  "@web/dev-server-esbuild": "^1.0.4",
57
57
  "@web/test-runner": "^0.20.2",
58
58
  "@web/test-runner-commands": "^0.9.0",
59
59
  "@web/test-runner-playwright": "^0.11.1",
60
60
  "@web/test-runner-visual-regression": "^0.10.0",
61
- "esbuild": "^0.25.5",
61
+ "esbuild": "^0.25.8",
62
62
  "istanbul-smart-text-reporter": "^1.1.5",
63
63
  "markdown-code-example-inserter": "^3.0.3",
64
- "typedoc": "0.28.5",
64
+ "typedoc": "^0.28.7",
65
65
  "typescript": "5.8.3",
66
- "vite": "^7.0.0",
66
+ "vite": "^7.0.6",
67
67
  "vite-tsconfig-paths": "^5.1.4"
68
68
  },
69
69
  "peerDependencies": {
70
- "element-vir": "^26.5.8"
70
+ "element-vir": "^26.6.1"
71
71
  },
72
72
  "engines": {
73
73
  "node": ">=22"
File without changes