vira 28.4.0 → 28.5.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.
@@ -15,4 +15,4 @@ export declare enum ViraCardState {
15
15
  */
16
16
  export declare const ViraCard: import("element-vir").DeclarativeElementDefinition<"vira-card", {
17
17
  cardState?: ViraCardState | undefined;
18
- }, {}, {}, "vira-card-error" | "vira-card-success", "vira-card-border" | "vira-card-border-radius" | "vira-card-error-color" | "vira-card-success-color" | "vira-card-padding", readonly [], readonly []>;
18
+ }, {}, {}, "vira-card-error" | "vira-card-success", "vira-card-border" | "vira-card-border-radius" | "vira-card-padding", readonly [], readonly []>;
@@ -1,4 +1,5 @@
1
1
  import { css, html } from 'element-vir';
2
+ import { viraFormCssVars } from '../styles/form-styles.js';
2
3
  import { defineViraElement } from './define-vira-element.js';
3
4
  /**
4
5
  * State options for {@link ViraCard}.
@@ -25,8 +26,6 @@ export const ViraCard = defineViraElement()({
25
26
  cssVars: {
26
27
  'vira-card-border': '1px solid #d3d3d3',
27
28
  'vira-card-border-radius': '16px',
28
- 'vira-card-error-color': 'red',
29
- 'vira-card-success-color': 'green',
30
29
  'vira-card-padding': '16px',
31
30
  },
32
31
  styles: ({ hostClasses, cssVars }) => css `
@@ -38,10 +37,10 @@ export const ViraCard = defineViraElement()({
38
37
  }
39
38
 
40
39
  ${hostClasses['vira-card-error'].selector} {
41
- border-color: ${cssVars['vira-card-error-color'].value};
40
+ border-color: ${viraFormCssVars['vira-form-error-foreground-color'].value};
42
41
  }
43
42
  ${hostClasses['vira-card-success'].selector} {
44
- border-color: ${cssVars['vira-card-success-color'].value};
43
+ border-color: ${viraFormCssVars['vira-form-success-foreground-color'].value};
45
44
  }
46
45
  `,
47
46
  render() {
@@ -4,4 +4,4 @@
4
4
  * @category Elements
5
5
  * @see https://electrovir.github.io/vira/book/elements/vira-error
6
6
  */
7
- export declare const ViraError: import("element-vir").DeclarativeElementDefinition<"vira-error", {}, {}, {}, "vira-error-", "vira-error-color" | "vira-error-font-weight", readonly [], readonly []>;
7
+ export declare const ViraError: import("element-vir").DeclarativeElementDefinition<"vira-error", {}, {}, {}, "vira-error-", "vira-error-font-weight", readonly [], readonly []>;
@@ -1,4 +1,5 @@
1
1
  import { css, html } from 'element-vir';
2
+ import { viraFormCssVars } from '../styles/form-styles.js';
2
3
  import { defineViraElement } from './define-vira-element.js';
3
4
  /**
4
5
  * An error wrapper that applies error coloring (red, by default).
@@ -9,12 +10,11 @@ import { defineViraElement } from './define-vira-element.js';
9
10
  export const ViraError = defineViraElement()({
10
11
  tagName: 'vira-error',
11
12
  cssVars: {
12
- 'vira-error-color': 'red',
13
13
  'vira-error-font-weight': 'bold',
14
14
  },
15
15
  styles: ({ cssVars }) => css `
16
16
  :host {
17
- color: ${cssVars['vira-error-color'].value};
17
+ color: ${viraFormCssVars['vira-form-error-foreground-color'].value};
18
18
  font-weight: ${cssVars['vira-error-font-weight'].value};
19
19
  }
20
20
  `,
@@ -1,3 +1,4 @@
1
+ import { type PartialWithUndefined } from '@augment-vir/common';
1
2
  import { type ViraIconSvg } from '../icons/index.js';
2
3
  import { type SharedTextInputElementInputs } from './shared-text-input-logic.js';
3
4
  export * from './shared-text-input-logic.js';
@@ -19,15 +20,24 @@ export declare enum ViraInputType {
19
20
  * @category Elements
20
21
  * @see https://electrovir.github.io/vira/book/elements/vira-input
21
22
  */
22
- export declare const ViraInput: import("element-vir").DeclarativeElementDefinition<"vira-input", {
23
- icon?: undefined | Pick<ViraIconSvg, "svgTemplate">;
24
- /** A suffix that, if provided, is shown following the user input field. */
25
- suffix?: string | undefined;
26
- showClearButton?: boolean | undefined;
27
- type?: ViraInputType;
28
- } & SharedTextInputElementInputs, {
23
+ export declare const ViraInput: import("element-vir").DeclarativeElementDefinition<"vira-input", Readonly<PartialWithUndefined<{
24
+ icon: Pick<ViraIconSvg, "svgTemplate">;
25
+ /** A suffix that, if provided, is shown following the input field. */
26
+ suffix: string;
27
+ /** A label that is shown above the input, if provided. */
28
+ label: string;
29
+ /** If true, applies error styling. */
30
+ hasError: boolean;
31
+ showClearButton: boolean;
32
+ type: ViraInputType;
33
+ }> & SharedTextInputElementInputs>, {
29
34
  forcedInputWidth: number;
30
35
  showPassword: boolean;
36
+ /**
37
+ * Used to couple the label and input together. This is not applied if no label is
38
+ * provided.
39
+ */
40
+ randomId: string;
31
41
  }, {
32
42
  /**
33
43
  * Fires whenever a user input created a new value. Does not fire if all input letters are
@@ -40,4 +50,4 @@ export declare const ViraInput: import("element-vir").DeclarativeElementDefiniti
40
50
  * that was blocked out of programmatic "value" property assignments.
41
51
  */
42
52
  inputBlocked: import("element-vir").DefineEvent<string>;
43
- }, "vira-input-disabled" | "vira-input-fit-text" | "vira-input-clear-button-shown", "vira-input-background-color" | "vira-input-placeholder-color" | "vira-input-text-color" | "vira-input-border-color" | "vira-input-text-selection-color" | "vira-input-action-button-color" | "vira-input-clear-button-hover-color" | "vira-input-clear-button-active-color" | "vira-input-show-password-button-hover-color" | "vira-input-show-password-button-active-color" | "vira-input-padding-horizontal" | "vira-input-padding-vertical", readonly [], readonly []>;
53
+ }, "vira-input-disabled" | "vira-input-fit-text" | "vira-input-clear-button-shown" | "vira-input-error", "vira-input-background-color" | "vira-input-placeholder-color" | "vira-input-text-color" | "vira-input-border-color" | "vira-input-text-selection-color" | "vira-input-action-button-color" | "vira-input-clear-button-hover-color" | "vira-input-clear-button-active-color" | "vira-input-show-password-button-hover-color" | "vira-input-show-password-button-active-color" | "vira-input-padding-horizontal" | "vira-input-padding-vertical" | "vira-input-label-font-weight", readonly [], readonly []>;
@@ -1,9 +1,11 @@
1
1
  import { assertWrap } from '@augment-vir/assert';
2
+ import { randomString } from '@augment-vir/common';
2
3
  import { extractEventTarget } from '@augment-vir/web';
3
4
  import { attributes, css, defineElementEvent, html, ifDefined, listen, nothing, onResize, renderIf, } from 'element-vir';
4
5
  import { CloseX24Icon } from '../icons/icon-svgs/close-x-24.icon.js';
5
6
  import { EyeClosed24Icon, EyeOpen24Icon } from '../icons/index.js';
6
7
  import { createFocusStyles } from '../styles/focus.js';
8
+ import { viraFormCssVars } from '../styles/form-styles.js';
7
9
  import { noUserSelect, viraAnimationDurations, viraBorders, viraDisabledStyles, } from '../styles/index.js';
8
10
  import { noNativeFormStyles } from '../styles/native-styles.js';
9
11
  import { defineViraElement } from './define-vira-element.js';
@@ -46,6 +48,7 @@ export const ViraInput = defineViraElement()({
46
48
  'vira-input-show-password-button-active-color': '#0261ba',
47
49
  'vira-input-padding-horizontal': '10px',
48
50
  'vira-input-padding-vertical': '6px',
51
+ 'vira-input-label-font-weight': 'bold',
49
52
  },
50
53
  styles: ({ hostClasses, cssVars }) => {
51
54
  return css `
@@ -57,6 +60,22 @@ export const ViraInput = defineViraElement()({
57
60
  color: ${cssVars['vira-input-text-color'].value};
58
61
  }
59
62
 
63
+ label {
64
+ display: flex;
65
+ flex-direction: column;
66
+ justify-content: flex-start;
67
+ gap: 2px;
68
+ width: 100%;
69
+ max-width: 100%;
70
+
71
+ & .input-label {
72
+ font-weight: ${cssVars['vira-input-label-font-weight'].value};
73
+ text-align: left;
74
+ flex-shrink: 0;
75
+ flex-wrap: wrap;
76
+ }
77
+ }
78
+
60
79
  ${hostClasses['vira-input-disabled'].selector} {
61
80
  ${viraDisabledStyles};
62
81
  }
@@ -226,6 +245,12 @@ export const ViraInput = defineViraElement()({
226
245
  .show-password-button:active {
227
246
  color: ${cssVars['vira-input-show-password-button-active-color'].value};
228
247
  }
248
+
249
+ ${hostClasses['vira-input-error'].selector} {
250
+ & .wrapper-border {
251
+ border-color: ${viraFormCssVars['vira-form-error-foreground-color'].value};
252
+ }
253
+ }
229
254
  `;
230
255
  },
231
256
  events: {
@@ -245,12 +270,18 @@ export const ViraInput = defineViraElement()({
245
270
  return {
246
271
  forcedInputWidth: 0,
247
272
  showPassword: false,
273
+ /**
274
+ * Used to couple the label and input together. This is not applied if no label is
275
+ * provided.
276
+ */
277
+ randomId: randomString(32),
248
278
  };
249
279
  },
250
280
  hostClasses: {
251
281
  'vira-input-disabled': ({ inputs }) => !!inputs.disabled,
252
282
  'vira-input-fit-text': ({ inputs }) => !!inputs.fitText,
253
283
  'vira-input-clear-button-shown': ({ inputs }) => !!inputs.showClearButton,
284
+ 'vira-input-error': ({ inputs }) => !!inputs.hasError,
254
285
  },
255
286
  render: ({ inputs, dispatch, state, updateState, events, host }) => {
256
287
  const { filtered: filteredValue } = filterTextInputValue({
@@ -274,11 +305,7 @@ export const ViraInput = defineViraElement()({
274
305
  * spellchecking).
275
306
  */
276
307
  inputs.type === ViraInputType.Password;
277
- /**
278
- * Don't use a wrapping `<label>` element here because it will mess with browser and
279
- * password manager autocomplete for passwords and usernames.
280
- */
281
- return html `
308
+ const inputTemplate = html `
282
309
  <span
283
310
  class="input-wrapper"
284
311
  ${listen('mousedown', (event) => {
@@ -305,6 +332,8 @@ export const ViraInput = defineViraElement()({
305
332
  `)}
306
333
 
307
334
  <input
335
+ id=${ifDefined(inputs.label ? state.randomId : undefined)}
336
+ aria-label=${ifDefined(inputs.label || undefined)}
308
337
  type=${calculateEffectiveInputType(inputs.type, state.showPassword)}
309
338
  style=${forcedInputWidthStyles}
310
339
  autocomplete=${ifDefined(shouldBlockBrowserHelps ? 'off' : undefined)}
@@ -377,6 +406,17 @@ export const ViraInput = defineViraElement()({
377
406
  <div class="border-style wrapper-border"></div>
378
407
  </span>
379
408
  `;
409
+ if (inputs.label) {
410
+ return html `
411
+ <label for=${state.randomId}>
412
+ <span class="input-label">${inputs.label}</span>
413
+ ${inputTemplate}
414
+ </label>
415
+ `;
416
+ }
417
+ else {
418
+ return inputTemplate;
419
+ }
380
420
  },
381
421
  });
382
422
  function calculateEffectiveInputType(type, showPassword) {
@@ -12,4 +12,6 @@ export declare const viraFormCssVars: import("lit-css-vars").CssVarDefinitions<{
12
12
  readonly 'vira-form-selection-hover-foreground-color': "black";
13
13
  readonly 'vira-form-selection-active-background-color': "#d2eaff";
14
14
  readonly 'vira-form-selection-active-foreground-color': "black";
15
+ readonly 'vira-form-error-foreground-color': "red";
16
+ readonly 'vira-form-success-foreground-color': "green";
15
17
  }>;
@@ -13,4 +13,6 @@ export const viraFormCssVars = defineCssVars({
13
13
  'vira-form-selection-hover-foreground-color': 'black',
14
14
  'vira-form-selection-active-background-color': '#d2eaff',
15
15
  'vira-form-selection-active-foreground-color': 'black',
16
+ 'vira-form-error-foreground-color': 'red',
17
+ 'vira-form-success-foreground-color': 'green',
16
18
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vira",
3
- "version": "28.4.0",
3
+ "version": "28.5.1",
4
4
  "description": "A simple and highly versatile design system using element-vir.",
5
5
  "keywords": [
6
6
  "design",