@inglorious/ui 0.1.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.
Files changed (83) hide show
  1. package/LICENSE +9 -0
  2. package/package.json +142 -0
  3. package/src/controls/button/button.stories.js +139 -0
  4. package/src/controls/button/index.js +5 -0
  5. package/src/controls/button/style.css +148 -0
  6. package/src/controls/button/template.js +74 -0
  7. package/src/controls/button-group/button-group.stories.js +108 -0
  8. package/src/controls/button-group/index.js +4 -0
  9. package/src/controls/button-group/style.css +58 -0
  10. package/src/controls/button-group/template.js +117 -0
  11. package/src/controls/checkbox/checkbox.stories.js +47 -0
  12. package/src/controls/checkbox/index.js +4 -0
  13. package/src/controls/checkbox/style.css +33 -0
  14. package/src/controls/checkbox/template.js +54 -0
  15. package/src/controls/fab/fab.stories.js +52 -0
  16. package/src/controls/fab/index.js +4 -0
  17. package/src/controls/fab/style.css +76 -0
  18. package/src/controls/fab/template.js +33 -0
  19. package/src/controls/icon-button/icon-button.stories.js +70 -0
  20. package/src/controls/icon-button/index.js +4 -0
  21. package/src/controls/icon-button/style.css +14 -0
  22. package/src/controls/icon-button/template.js +47 -0
  23. package/src/controls/input/index.js +4 -0
  24. package/src/controls/input/input.stories.js +180 -0
  25. package/src/controls/input/style.css +121 -0
  26. package/src/controls/input/template.js +111 -0
  27. package/src/controls/radio-group/index.js +4 -0
  28. package/src/controls/radio-group/radio-group.stories.js +51 -0
  29. package/src/controls/radio-group/style.css +41 -0
  30. package/src/controls/radio-group/template.js +71 -0
  31. package/src/controls/rating/index.js +4 -0
  32. package/src/controls/rating/rating.stories.js +47 -0
  33. package/src/controls/rating/style.css +29 -0
  34. package/src/controls/rating/template.js +53 -0
  35. package/src/controls/select/handlers.js +133 -0
  36. package/src/controls/select/helpers.js +91 -0
  37. package/src/controls/select/index.js +15 -0
  38. package/src/controls/select/select.stories.js +90 -0
  39. package/src/controls/select/style.css +211 -0
  40. package/src/controls/select/template.js +423 -0
  41. package/src/controls/slider/index.js +4 -0
  42. package/src/controls/slider/slider.stories.js +43 -0
  43. package/src/controls/slider/style.css +28 -0
  44. package/src/controls/slider/template.js +66 -0
  45. package/src/controls/switch/index.js +4 -0
  46. package/src/controls/switch/style.css +82 -0
  47. package/src/controls/switch/switch.stories.js +45 -0
  48. package/src/controls/switch/template.js +55 -0
  49. package/src/index.js +14 -0
  50. package/src/layout/flex/flex.stories.js +103 -0
  51. package/src/layout/flex/index.js +4 -0
  52. package/src/layout/flex/style.css +103 -0
  53. package/src/layout/flex/template.js +41 -0
  54. package/src/layout/grid/grid.stories.js +82 -0
  55. package/src/layout/grid/index.js +4 -0
  56. package/src/layout/grid/style.css +51 -0
  57. package/src/layout/grid/template.js +47 -0
  58. package/src/shared/applyElementProps.js +79 -0
  59. package/src/shared/withRenderValidation.js +19 -0
  60. package/src/stories/notifyStory.js +43 -0
  61. package/src/themes/bootstrap.css +118 -0
  62. package/src/themes/inglorious.css +106 -0
  63. package/src/themes/material.css +124 -0
  64. package/src/tokens/index.css +133 -0
  65. package/src/widgets/card/card.stories.js +135 -0
  66. package/src/widgets/card/index.js +4 -0
  67. package/src/widgets/card/style.css +53 -0
  68. package/src/widgets/card/template.js +97 -0
  69. package/types/controls/button-group.d.ts +35 -0
  70. package/types/controls/button.d.ts +23 -0
  71. package/types/controls/checkbox.d.ts +18 -0
  72. package/types/controls/fab.d.ts +19 -0
  73. package/types/controls/icon-button.d.ts +23 -0
  74. package/types/controls/input.d.ts +29 -0
  75. package/types/controls/radio-group.d.ts +25 -0
  76. package/types/controls/rating.d.ts +18 -0
  77. package/types/controls/select.d.ts +56 -0
  78. package/types/controls/slider.d.ts +21 -0
  79. package/types/controls/switch.d.ts +17 -0
  80. package/types/index.d.ts +14 -0
  81. package/types/layout/flex.d.ts +20 -0
  82. package/types/layout/grid.d.ts +19 -0
  83. package/types/widgets/card.d.ts +21 -0
@@ -0,0 +1,180 @@
1
+ import {
2
+ makeStoryRender,
3
+ notifyActionArgType,
4
+ } from "../../stories/notifyStory.js"
5
+ import { input } from "."
6
+
7
+ export default {
8
+ title: "Controls/Input",
9
+ tags: ["autodocs"],
10
+ render: makeStoryRender(input, "story-input"),
11
+ argTypes: {
12
+ ...notifyActionArgType,
13
+ label: {
14
+ control: "text",
15
+ description: "Field label rendered above the input.",
16
+ },
17
+ placeholder: {
18
+ control: "text",
19
+ description: "Placeholder text shown when value is empty.",
20
+ },
21
+ name: {
22
+ control: "text",
23
+ description: "Native HTML input name attribute.",
24
+ },
25
+ type: {
26
+ control: "select",
27
+ options: ["text", "email", "password", "number", "tel", "url", "search"],
28
+ description: "Native HTML input type.",
29
+ },
30
+ inputmode: {
31
+ control: "select",
32
+ options: [
33
+ "none",
34
+ "text",
35
+ "decimal",
36
+ "numeric",
37
+ "tel",
38
+ "search",
39
+ "email",
40
+ "url",
41
+ ],
42
+ description: "Native inputmode hint for virtual keyboards.",
43
+ },
44
+ value: {
45
+ control: "text",
46
+ description: "Current input value.",
47
+ },
48
+ hint: {
49
+ control: "text",
50
+ description: "Helper text shown below the field when there is no error.",
51
+ },
52
+ error: {
53
+ control: "text",
54
+ description: "Validation message shown below the field.",
55
+ },
56
+ size: {
57
+ control: "select",
58
+ options: ["sm", "md", "lg"],
59
+ description: "Size scale for paddings and font-size.",
60
+ },
61
+ disabled: {
62
+ control: "boolean",
63
+ description: "Disables user input and interaction.",
64
+ },
65
+ readonly: {
66
+ control: "boolean",
67
+ description: "Prevents editing while keeping the field focusable.",
68
+ },
69
+ required: {
70
+ control: "boolean",
71
+ description: "Marks the field as required.",
72
+ },
73
+ fullWidth: {
74
+ control: "boolean",
75
+ description: "Expands input width to 100% of its container.",
76
+ },
77
+ },
78
+ parameters: {
79
+ docs: {
80
+ description: {
81
+ component:
82
+ "Text field control with labels, hints, errors, and semantic states.",
83
+ },
84
+ },
85
+ },
86
+ }
87
+ export const Default = {}
88
+ Default.args = {
89
+ label: "Username",
90
+ placeholder: "Enter your username",
91
+ name: "username",
92
+ type: "text",
93
+ value: "",
94
+ hint: "",
95
+ error: "",
96
+ size: "md",
97
+ disabled: false,
98
+ readonly: false,
99
+ required: false,
100
+ fullWidth: false,
101
+ }
102
+
103
+ export const WithHint = {}
104
+ WithHint.args = {
105
+ ...Default.args,
106
+ label: "Email",
107
+ type: "email",
108
+ placeholder: "you@example.com",
109
+ hint: "We'll never share your email",
110
+ }
111
+
112
+ export const WithError = {}
113
+ WithError.args = {
114
+ ...Default.args,
115
+ label: "Email",
116
+ type: "email",
117
+ value: "invalid-email",
118
+ error: "Please enter a valid email address",
119
+ }
120
+
121
+ export const Required = {}
122
+ Required.args = {
123
+ ...Default.args,
124
+ label: "Password",
125
+ type: "password",
126
+ placeholder: "Enter your password",
127
+ required: true,
128
+ }
129
+
130
+ export const Disabled = {}
131
+ Disabled.args = {
132
+ ...Default.args,
133
+ label: "Disabled Input",
134
+ disabled: true,
135
+ value: "Cannot edit",
136
+ }
137
+
138
+ export const Readonly = {}
139
+ Readonly.args = {
140
+ ...Default.args,
141
+ label: "Readonly Input",
142
+ readonly: true,
143
+ value: "Read-only value",
144
+ }
145
+
146
+ export const Small = {}
147
+ Small.args = {
148
+ ...Default.args,
149
+ label: "Small Input",
150
+ size: "sm",
151
+ }
152
+
153
+ export const Large = {}
154
+ Large.args = {
155
+ ...Default.args,
156
+ label: "Large Input",
157
+ size: "lg",
158
+ }
159
+
160
+ export const FullWidth = {}
161
+ FullWidth.args = {
162
+ ...Default.args,
163
+ label: "Full Width Input",
164
+ placeholder: "This input takes full width",
165
+ fullWidth: true,
166
+ }
167
+
168
+ export const Number = {}
169
+ Number.args = {
170
+ ...Default.args,
171
+ label: "Amount",
172
+ type: "number",
173
+ value: "1234.56",
174
+ placeholder: "0.00",
175
+ min: "0",
176
+ max: "10000",
177
+ step: "0.01",
178
+ inputmode: "decimal",
179
+ "data-testid": "amount-input",
180
+ }
@@ -0,0 +1,121 @@
1
+ .iw-input-field {
2
+ display: flex;
3
+ flex-direction: column;
4
+ gap: var(--iw-space-1);
5
+ font-family: var(--iw-font-family-sans);
6
+
7
+ &.iw-input-full-width {
8
+ width: 100%;
9
+ }
10
+
11
+ .iw-input-label {
12
+ font-size: var(--iw-font-size-sm);
13
+ font-weight: var(--iw-font-weight-medium);
14
+ color: var(--iw-color-text);
15
+ }
16
+
17
+ .iw-input-required {
18
+ color: var(--iw-color-error);
19
+ margin-left: var(--iw-space-1);
20
+ }
21
+
22
+ .iw-input-frame {
23
+ position: relative;
24
+ display: flex;
25
+ align-items: center;
26
+ }
27
+
28
+ .iw-input {
29
+ width: 100%;
30
+ padding: var(--iw-space-2) var(--iw-space-3);
31
+ font-family: inherit;
32
+ font-size: var(--iw-font-size-base);
33
+ line-height: var(--iw-line-height-normal);
34
+ color: var(--iw-input-text);
35
+ background-color: var(--iw-input-bg);
36
+ border: 1px solid var(--iw-input-border);
37
+ border-radius: var(--iw-input-radius);
38
+ outline: none;
39
+ transition: all var(--iw-transition-fast);
40
+
41
+ &::placeholder {
42
+ color: var(--iw-input-text-placeholder);
43
+ }
44
+
45
+ &:hover:not(:disabled) {
46
+ background-color: var(--iw-input-bg-hover);
47
+ border-color: var(--iw-input-border-hover);
48
+ }
49
+
50
+ &:focus:not(:disabled) {
51
+ background-color: var(--iw-input-bg-focus);
52
+ border-color: var(--iw-input-border-focus);
53
+ box-shadow: var(--iw-input-shadow-focus);
54
+ }
55
+
56
+ &:disabled {
57
+ opacity: 0.5;
58
+ cursor: not-allowed;
59
+ }
60
+
61
+ &.iw-input-error {
62
+ border-color: var(--iw-color-error);
63
+
64
+ &:focus {
65
+ border-color: var(--iw-color-error);
66
+ box-shadow: 0 0 0 1px var(--iw-color-error);
67
+ }
68
+ }
69
+
70
+ &.iw-input-number {
71
+ text-align: right;
72
+ }
73
+
74
+ &.iw-input-sm {
75
+ padding: var(--iw-space-1) var(--iw-space-2);
76
+ font-size: var(--iw-font-size-sm);
77
+ }
78
+
79
+ &.iw-input-lg {
80
+ padding: var(--iw-space-3) var(--iw-space-4);
81
+ font-size: var(--iw-font-size-lg);
82
+ }
83
+ }
84
+
85
+ .iw-input-icon {
86
+ position: absolute;
87
+ left: var(--iw-space-3);
88
+ display: flex;
89
+ align-items: center;
90
+ justify-content: center;
91
+ color: var(--iw-color-text-muted);
92
+ pointer-events: none;
93
+
94
+ &.iw-input-icon-after {
95
+ left: auto;
96
+ right: var(--iw-space-3);
97
+ }
98
+ }
99
+
100
+ &.iw-input-has-icon .iw-input {
101
+ padding-left: calc(var(--iw-space-3) * 2 + 1em);
102
+ }
103
+
104
+ &.iw-input-has-icon-after .iw-input {
105
+ padding-right: calc(var(--iw-space-3) * 2 + 1em);
106
+ }
107
+
108
+ .iw-input-hint,
109
+ .iw-input-error-message {
110
+ font-size: var(--iw-font-size-sm);
111
+ line-height: var(--iw-line-height-normal);
112
+ }
113
+
114
+ .iw-input-hint {
115
+ color: var(--iw-color-text-muted);
116
+ }
117
+
118
+ .iw-input-error-message {
119
+ color: var(--iw-color-error);
120
+ }
121
+ }
@@ -0,0 +1,111 @@
1
+ /**
2
+ * @typedef {import('../../../types/controls/input').InputEntity} InputEntity
3
+ * @typedef {import('@inglorious/web').Api} Api
4
+ * @typedef {import('@inglorious/web').TemplateResult} TemplateResult
5
+ */
6
+
7
+ import { classMap, html, ref } from "@inglorious/web"
8
+
9
+ import { applyElementProps } from "@/shared/applyElementProps.js"
10
+
11
+ /**
12
+ * Input component for Inglorious Web.
13
+ *
14
+ * @example
15
+ * // Stateless usage
16
+ * input.render({ label: 'Email', type: 'email', placeholder: 'you@example.com' }, api)
17
+ *
18
+ * @example
19
+ * // Stateful usage with event handling
20
+ * // Entity: { type: 'input', id: 'emailInput', label: 'Email' }
21
+ * // In store: api.render('emailInput')
22
+ *
23
+ * @param {InputEntity} entity
24
+ * @param {Api} api
25
+ * @returns {TemplateResult}
26
+ */
27
+ export function render(entity, api) {
28
+ const {
29
+ name = "",
30
+ type = "text",
31
+ value = "",
32
+ placeholder = "",
33
+ label,
34
+ hint,
35
+ error,
36
+ size = "md",
37
+ disabled = false,
38
+ readonly = false,
39
+ required = false,
40
+ fullWidth = false,
41
+ icon,
42
+ iconAfter,
43
+ ...rest
44
+ } = entity
45
+
46
+ const inputId = entity.id || name
47
+
48
+ const wrapperClasses = {
49
+ "iw-input-field": true,
50
+ "iw-input-full-width": fullWidth,
51
+ "iw-input-disabled": disabled,
52
+ "iw-input-has-error": !!error,
53
+ "iw-input-has-icon": !!icon,
54
+ "iw-input-has-icon-after": !!iconAfter,
55
+ }
56
+
57
+ const inputClasses = {
58
+ "iw-input": true,
59
+ [`iw-input-${size}`]: size !== "md",
60
+ "iw-input-error": !!error,
61
+ "iw-input-number": type === "number",
62
+ }
63
+
64
+ return html`
65
+ <div class=${classMap(wrapperClasses)}>
66
+ ${label
67
+ ? html`
68
+ <label for=${inputId} class="iw-input-label">
69
+ ${label}
70
+ ${required
71
+ ? html`<span class="iw-input-required">*</span>`
72
+ : null}
73
+ </label>
74
+ `
75
+ : null}
76
+
77
+ <div class="iw-input-frame">
78
+ ${icon ? html`<span class="iw-input-icon">${icon}</span>` : null}
79
+
80
+ <input
81
+ id=${inputId}
82
+ name=${name}
83
+ type=${type}
84
+ .value=${value}
85
+ placeholder=${placeholder}
86
+ ?disabled=${disabled}
87
+ ?readonly=${readonly}
88
+ ?required=${required}
89
+ class=${classMap(inputClasses)}
90
+ @input=${(event) =>
91
+ api.notify(`#${entity.id}:change`, event.target.value)}
92
+ @blur=${() => api.notify(`#${entity.id}:blur`)}
93
+ @focus=${() => api.notify(`#${entity.id}:focus`)}
94
+ ${ref((element) => applyElementProps(element, rest))}
95
+ />
96
+
97
+ ${iconAfter
98
+ ? html`<span class="iw-input-icon iw-input-icon-after"
99
+ >${iconAfter}</span
100
+ >`
101
+ : null}
102
+ </div>
103
+
104
+ ${error
105
+ ? html`<span class="iw-input-error-message">${error}</span>`
106
+ : hint
107
+ ? html`<span class="iw-input-hint">${hint}</span>`
108
+ : null}
109
+ </div>
110
+ `
111
+ }
@@ -0,0 +1,4 @@
1
+ import { withRenderValidation } from "../../shared/withRenderValidation.js"
2
+ import * as renderers from "./template.js"
3
+
4
+ export const radioGroup = [{ ...renderers }, withRenderValidation]
@@ -0,0 +1,51 @@
1
+ import {
2
+ makeStoryRender,
3
+ notifyActionArgType,
4
+ } from "../../stories/notifyStory.js"
5
+ import { radioGroup } from "."
6
+
7
+ export default {
8
+ title: "Controls/RadioGroup",
9
+ tags: ["autodocs"],
10
+ render: makeStoryRender(radioGroup, "story-radio-group"),
11
+ argTypes: {
12
+ ...notifyActionArgType,
13
+ label: { control: "text", description: "Fieldset label." },
14
+ name: { control: "text", description: "Native radio input name." },
15
+ value: { control: "text", description: "Selected option value." },
16
+ direction: {
17
+ control: "select",
18
+ options: ["column", "row"],
19
+ description: "Layout direction for options.",
20
+ },
21
+ disabled: { control: "boolean", description: "Disables all options." },
22
+ options: { control: "object", description: "List of radio options." },
23
+ },
24
+ parameters: {
25
+ docs: {
26
+ description: {
27
+ component: "Single-choice control rendered from an options array.",
28
+ },
29
+ },
30
+ },
31
+ }
32
+
33
+ export const Default = {}
34
+ Default.args = {
35
+ label: "Priority",
36
+ name: "priority",
37
+ value: "medium",
38
+ direction: "column",
39
+ disabled: false,
40
+ options: [
41
+ { label: "Low", value: "low" },
42
+ { label: "Medium", value: "medium" },
43
+ { label: "High", value: "high" },
44
+ ],
45
+ }
46
+
47
+ export const Row = {}
48
+ Row.args = {
49
+ ...Default.args,
50
+ direction: "row",
51
+ }
@@ -0,0 +1,41 @@
1
+ .iw-radio-group {
2
+ border: 0;
3
+ margin: 0;
4
+ padding: 0;
5
+ font-family: var(--iw-font-family-sans);
6
+
7
+ .iw-radio-group-label {
8
+ margin-bottom: var(--iw-space-2);
9
+ font-size: var(--iw-font-size-sm);
10
+ color: var(--iw-color-text-secondary);
11
+ }
12
+
13
+ .iw-radio-option {
14
+ display: inline-flex;
15
+ align-items: center;
16
+ gap: var(--iw-space-2);
17
+ color: var(--iw-color-text);
18
+ cursor: pointer;
19
+ }
20
+
21
+ .iw-radio {
22
+ margin: 0;
23
+ accent-color: var(--iw-color-primary);
24
+ }
25
+
26
+ &.iw-radio-group-column {
27
+ display: flex;
28
+ flex-direction: column;
29
+ gap: var(--iw-space-2);
30
+ }
31
+
32
+ &.iw-radio-group-row {
33
+ display: inline-flex;
34
+ align-items: center;
35
+ gap: var(--iw-space-4);
36
+ }
37
+
38
+ &.iw-radio-group-disabled {
39
+ opacity: 0.6;
40
+ }
41
+ }
@@ -0,0 +1,71 @@
1
+ /**
2
+ * @typedef {import('../../../types/controls/radio-group').RadioGroupEntity} RadioGroupEntity
3
+ * @typedef {import('@inglorious/web').Api} Api
4
+ * @typedef {import('@inglorious/web').TemplateResult} TemplateResult
5
+ */
6
+
7
+ import { classMap, html, ref } from "@inglorious/web"
8
+
9
+ import { applyElementProps } from "@/shared/applyElementProps.js"
10
+
11
+ /**
12
+ * Radio group control for selecting one option.
13
+ *
14
+ * @param {RadioGroupEntity} entity
15
+ * @param {Api} api
16
+ * @returns {TemplateResult}
17
+ */
18
+ export function render(entity, api) {
19
+ const {
20
+ name = entity.id || "radio",
21
+ label,
22
+ value,
23
+ options = [],
24
+ direction = "column",
25
+ disabled = false,
26
+ ...rest
27
+ } = entity
28
+
29
+ const rootClasses = {
30
+ "iw-radio-group": true,
31
+ [`iw-radio-group-${direction}`]: true,
32
+ "iw-radio-group-disabled": disabled,
33
+ }
34
+
35
+ return html`
36
+ <fieldset
37
+ class=${classMap(rootClasses)}
38
+ ?disabled=${disabled}
39
+ ${ref((element) => applyElementProps(element, rest))}
40
+ >
41
+ ${label
42
+ ? html`<legend class="iw-radio-group-label">${label}</legend>`
43
+ : null}
44
+ ${options.map((option) => {
45
+ const {
46
+ label: optionLabel,
47
+ value: optionValue,
48
+ disabled: optionDisabled = false,
49
+ ...optionRest
50
+ } = option
51
+
52
+ return html`
53
+ <label class="iw-radio-option">
54
+ <input
55
+ class="iw-radio"
56
+ type="radio"
57
+ name=${name}
58
+ value=${optionValue}
59
+ .checked=${value === optionValue}
60
+ ?disabled=${disabled || optionDisabled}
61
+ @change=${(event) =>
62
+ api.notify(`#${entity.id}:change`, event.target.value)}
63
+ ${ref((element) => applyElementProps(element, optionRest))}
64
+ />
65
+ <span>${optionLabel}</span>
66
+ </label>
67
+ `
68
+ })}
69
+ </fieldset>
70
+ `
71
+ }
@@ -0,0 +1,4 @@
1
+ import { withRenderValidation } from "../../shared/withRenderValidation.js"
2
+ import * as renderers from "./template.js"
3
+
4
+ export const rating = [{ ...renderers }, withRenderValidation]
@@ -0,0 +1,47 @@
1
+ import {
2
+ makeStoryRender,
3
+ notifyActionArgType,
4
+ } from "../../stories/notifyStory.js"
5
+ import { rating } from "."
6
+
7
+ export default {
8
+ title: "Controls/Rating",
9
+ tags: ["autodocs"],
10
+ render: makeStoryRender(rating, "story-rating"),
11
+ argTypes: {
12
+ ...notifyActionArgType,
13
+ value: { control: "number", description: "Current rating value." },
14
+ max: { control: "number", description: "Maximum rating value." },
15
+ disabled: { control: "boolean", description: "Disables interaction." },
16
+ readonly: {
17
+ control: "boolean",
18
+ description: "Shows value without interaction.",
19
+ },
20
+ symbol: { control: "text", description: "Filled symbol." },
21
+ emptySymbol: { control: "text", description: "Unfilled symbol." },
22
+ size: {
23
+ control: "select",
24
+ options: ["sm", "md", "lg"],
25
+ description: "Symbol size.",
26
+ },
27
+ },
28
+ parameters: {
29
+ docs: {
30
+ description: {
31
+ component:
32
+ "Discrete rating selector rendered as stars (or custom symbols).",
33
+ },
34
+ },
35
+ },
36
+ }
37
+
38
+ export const Default = {}
39
+ Default.args = {
40
+ value: 3,
41
+ max: 5,
42
+ disabled: false,
43
+ readonly: false,
44
+ symbol: "★",
45
+ emptySymbol: "☆",
46
+ size: "md",
47
+ }
@@ -0,0 +1,29 @@
1
+ .iw-rating {
2
+ display: inline-flex;
3
+ align-items: center;
4
+ gap: var(--iw-space-1);
5
+
6
+ .iw-rating-item {
7
+ border: 0;
8
+ background: transparent;
9
+ padding: 0;
10
+ margin: 0;
11
+ cursor: pointer;
12
+ color: var(--iw-color-warning);
13
+ font-size: 1.25rem;
14
+ line-height: 1;
15
+ }
16
+
17
+ &.iw-rating-sm .iw-rating-item {
18
+ font-size: 1rem;
19
+ }
20
+
21
+ &.iw-rating-lg .iw-rating-item {
22
+ font-size: 1.5rem;
23
+ }
24
+
25
+ &.iw-rating-disabled,
26
+ &.iw-rating-readonly {
27
+ opacity: 0.6;
28
+ }
29
+ }