@realmorg/ui 0.0.0-stage → 2.0.0-alpha.3

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 (66) hide show
  1. package/LICENSE +7 -0
  2. package/README.md +44 -2
  3. package/components/accordion.html +139 -0
  4. package/components/alert-dialog.html +236 -0
  5. package/components/alert.html +83 -0
  6. package/components/aspect-ratio.html +29 -0
  7. package/components/attachment.html +98 -0
  8. package/components/avatar.html +149 -0
  9. package/components/badge.html +62 -0
  10. package/components/breadcrumb.html +159 -0
  11. package/components/bubble.html +77 -0
  12. package/components/button-group.html +98 -0
  13. package/components/button.html +194 -0
  14. package/components/calendar.html +176 -0
  15. package/components/card.html +143 -0
  16. package/components/carousel.html +208 -0
  17. package/components/chart.html +168 -0
  18. package/components/checkbox.html +99 -0
  19. package/components/code-block.html +64 -0
  20. package/components/collapsible.html +90 -0
  21. package/components/combobox.html +237 -0
  22. package/components/command.html +201 -0
  23. package/components/context-menu.html +81 -0
  24. package/components/dialog.html +327 -0
  25. package/components/direction.html +23 -0
  26. package/components/drawer.html +267 -0
  27. package/components/dropdown-menu.html +421 -0
  28. package/components/empty.html +132 -0
  29. package/components/field.html +143 -0
  30. package/components/hover-card.html +111 -0
  31. package/components/input-group.html +91 -0
  32. package/components/input-otp.html +151 -0
  33. package/components/input.html +94 -0
  34. package/components/item.html +208 -0
  35. package/components/kbd.html +45 -0
  36. package/components/label.html +46 -0
  37. package/components/marker.html +41 -0
  38. package/components/menubar.html +137 -0
  39. package/components/message-scroller.html +68 -0
  40. package/components/message.html +95 -0
  41. package/components/navigation-menu.html +233 -0
  42. package/components/pagination.html +160 -0
  43. package/components/popover.html +164 -0
  44. package/components/progress.html +45 -0
  45. package/components/radio-group.html +120 -0
  46. package/components/resizable.html +170 -0
  47. package/components/scroll-area.html +56 -0
  48. package/components/select.html +103 -0
  49. package/components/separator.html +31 -0
  50. package/components/sheet.html +173 -0
  51. package/components/sidebar.html +393 -0
  52. package/components/skeleton.html +36 -0
  53. package/components/slider.html +108 -0
  54. package/components/spinner.html +53 -0
  55. package/components/switch.html +95 -0
  56. package/components/table.html +81 -0
  57. package/components/tabs.html +182 -0
  58. package/components/textarea.html +80 -0
  59. package/components/toaster.html +134 -0
  60. package/components/toggle-group.html +71 -0
  61. package/components/toggle.html +87 -0
  62. package/components/tooltip.html +114 -0
  63. package/dist/theme.css +158 -0
  64. package/dist/ui.html +7923 -0
  65. package/package.json +40 -3
  66. package/theme.css +158 -0
@@ -0,0 +1,56 @@
1
+ <custom-element name="ui-scroll-area">
2
+ <script>
3
+ defineProps({
4
+ orientation: prop.enum(["vertical", "horizontal", "both"]).default("vertical"),
5
+ variant: prop.enum(["default", "outline"]).default("default"),
6
+ });
7
+ </script>
8
+
9
+ <style>
10
+ /* A double tap must not zoom the page. Set inside the shadow root, because a page-level
11
+ touch-action does not reach shadow content in iOS Safari. */
12
+ :host,
13
+ * {
14
+ touch-action: manipulation;
15
+ }
16
+ :host {
17
+ display: block;
18
+ position: relative;
19
+ box-sizing: border-box;
20
+ overflow: hidden;
21
+ border-radius: inherit;
22
+ }
23
+ :host(:state(attr-width)) {
24
+ width: calc(var(--spacing) * var(--attr-width));
25
+ }
26
+ :host(:state(attr-height)) {
27
+ height: calc(var(--spacing) * var(--attr-height));
28
+ }
29
+ :host(:state(attr-variant-is-outline)) {
30
+ border: 1px solid var(--border);
31
+ border-radius: var(--radius-md);
32
+ }
33
+ .viewport {
34
+ width: 100%;
35
+ height: 100%;
36
+ overflow-y: auto;
37
+ overflow-x: hidden;
38
+ scrollbar-width: thin;
39
+ scrollbar-color: var(--border) transparent;
40
+ border-radius: inherit;
41
+ outline: none;
42
+ }
43
+ :host(:state(attr-orientation-is-horizontal)) .viewport {
44
+ overflow-x: auto;
45
+ overflow-y: hidden;
46
+ }
47
+ :host(:state(attr-orientation-is-both)) .viewport {
48
+ overflow: auto;
49
+ }
50
+ .viewport:focus-visible {
51
+ box-shadow: var(--focus-ring);
52
+ }
53
+ </style>
54
+
55
+ <div class="viewport" part="viewport" tabindex="0"><slot></slot></div>
56
+ </custom-element>
@@ -0,0 +1,103 @@
1
+ <custom-element name="ui-select" form-associated delegates-focus>
2
+ <script>
3
+ const props = defineProps({
4
+ value: prop.string().default(""),
5
+ placeholder: prop.string(),
6
+ size: prop.enum(["default", "sm"]).default("default"),
7
+ disabled: prop.boolean(),
8
+ required: prop.boolean(),
9
+ label: prop.string().attribute("aria-label"),
10
+ });
11
+
12
+ const options = useChildren("option", ["value", "label", "disabled", "selected"]);
13
+ const menu = useState({
14
+ get empty() {
15
+ return !props.value;
16
+ },
17
+ get options() {
18
+ return options.map((option, index) => ({
19
+ id: `${index}:${option.value}`,
20
+ value: option.value,
21
+ label: option.label,
22
+ disabled: option.disabled,
23
+ selected: option.value === props.value,
24
+ }));
25
+ },
26
+ });
27
+
28
+ observe(() => {
29
+ if (props.placeholder || !options.length || menu.options.some((option) => option.selected)) return;
30
+ props.value = (options.find((option) => option.hasAttribute("selected")) ?? options[0]).value;
31
+ });
32
+ </script>
33
+
34
+ <style>
35
+ /* A double tap must not zoom the page. Set inside the shadow root, because a page-level
36
+ touch-action does not reach shadow content in iOS Safari. */
37
+ :host,
38
+ * {
39
+ touch-action: manipulation;
40
+ }
41
+ :host {
42
+ display: block;
43
+ min-width: calc(var(--spacing) * 32);
44
+ }
45
+ :host(:state(attr-width)) {
46
+ width: calc(var(--spacing) * var(--attr-width));
47
+ }
48
+ select {
49
+ box-sizing: border-box;
50
+ width: 100%;
51
+ height: calc(var(--spacing) * 9);
52
+ padding: 0 calc(var(--spacing) * 8) 0 calc(var(--spacing) * 3);
53
+ border: 1px solid var(--input);
54
+ border-radius: var(--radius-md);
55
+ background: transparent
56
+ url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none' stroke='%23888' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E")
57
+ no-repeat right calc(var(--spacing) * 2) center;
58
+ color: inherit;
59
+ font: inherit;
60
+ font-size: var(--text-sm);
61
+ box-shadow: var(--shadow-xs);
62
+ appearance: none;
63
+ outline: none;
64
+ cursor: pointer;
65
+ }
66
+ /* iOS Safari zooms in on a focused field whose text is under 16px. */
67
+ @media (pointer: coarse) {
68
+ select {
69
+ font-size: var(--text-base);
70
+ }
71
+ }
72
+ :host(:state(attr-size-is-sm)) select {
73
+ height: calc(var(--spacing) * 8);
74
+ }
75
+ select:focus-visible {
76
+ border-color: var(--ring);
77
+ box-shadow: var(--focus-ring);
78
+ }
79
+ select:disabled {
80
+ cursor: not-allowed;
81
+ opacity: 0.5;
82
+ }
83
+ option {
84
+ background: var(--popover);
85
+ color: var(--popover-foreground);
86
+ }
87
+ .source {
88
+ display: none;
89
+ }
90
+ </style>
91
+
92
+ <select
93
+ ref="control"
94
+ _aria-label="@label"
95
+ part="control"
96
+ _disabled="@disabled"
97
+ _required="@required"
98
+ >
99
+ <option value="" disabled _hidden="!@placeholder" _label="@placeholder" _selected="#menu.empty"></option>
100
+ <option repeat="#menu.options" as="option" key="id" _value="#option.value" _label="#option.label" _selected="#option.selected" _disabled="#option.disabled"></option>
101
+ </select>
102
+ <div class="source"><slot></slot></div>
103
+ </custom-element>
@@ -0,0 +1,31 @@
1
+ <custom-element name="ui-separator" role="separator">
2
+ <script>
3
+ const props = defineProps({
4
+ orientation: prop.enum(["horizontal", "vertical"]).default("horizontal"),
5
+ });
6
+ observe(() => {
7
+ internals.ariaOrientation = props.orientation;
8
+ });
9
+ </script>
10
+
11
+ <style>
12
+ /* A double tap must not zoom the page. Set inside the shadow root, because a page-level
13
+ touch-action does not reach shadow content in iOS Safari. */
14
+ :host,
15
+ * {
16
+ touch-action: manipulation;
17
+ }
18
+ :host {
19
+ display: block;
20
+ flex-shrink: 0;
21
+ height: 1px;
22
+ width: 100%;
23
+ background: var(--border);
24
+ }
25
+ :host(:state(attr-orientation-is-vertical)) {
26
+ height: auto;
27
+ width: 1px;
28
+ align-self: stretch;
29
+ }
30
+ </style>
31
+ </custom-element>
@@ -0,0 +1,173 @@
1
+ <import-element from="./dialog.html"></import-element>
2
+
3
+ <custom-element name="ui-sheet">
4
+ <script>
5
+ const props = defineProps({
6
+ open: prop.boolean().reflect(),
7
+ side: prop.enum(["top", "right", "bottom", "left"]).default("right"),
8
+ });
9
+
10
+ const parts = useChildren("ui-sheet-header, ui-sheet-title, ui-sheet-description");
11
+ const sheet = useState({
12
+ get label() {
13
+ return text("ui-sheet-title");
14
+ },
15
+ get description() {
16
+ return text("ui-sheet-description");
17
+ },
18
+ });
19
+
20
+ function text(selector) {
21
+ const found = parts.flatMap((part) => (part.matches(selector) ? [part] : [...part.querySelectorAll(selector)]));
22
+ return found.map((part) => part.textContent.trim()).join(" ") || null;
23
+ }
24
+
25
+ function show() {
26
+ props.open = true;
27
+ }
28
+
29
+ function showFrom(trigger) {
30
+ trigger.firstElementChild?.focus();
31
+ show();
32
+ }
33
+
34
+ function close() {
35
+ props.open = false;
36
+ }
37
+
38
+ function requestClose() {
39
+ refs.dialog.requestClose();
40
+ }
41
+
42
+ function closed() {
43
+ props.open = false;
44
+ dispatch("close", undefined, { bubbles: false, composed: false });
45
+ }
46
+
47
+ const COMMANDS = { "show-modal": show, close, "request-close": requestClose };
48
+
49
+ defineMethods({ showModal: show, show, close, requestClose });
50
+
51
+ listen("command", (event) => COMMANDS[event.command.replace(/^--/, "")]?.());
52
+ </script>
53
+
54
+ <style>
55
+ /* A double tap must not zoom the page. Set inside the shadow root, because a page-level
56
+ touch-action does not reach shadow content in iOS Safari. */
57
+ :host,
58
+ * {
59
+ touch-action: manipulation;
60
+ }
61
+ :host {
62
+ display: contents;
63
+ }
64
+ </style>
65
+
66
+ <slot name="trigger"></slot>
67
+ <ui-dialog ref="dialog" part="dialog" _side="@side" _open="@open" _label="#sheet.label" _description="#sheet.description" onclose="closed()">
68
+ <slot name="header" slot="header"></slot>
69
+ <slot></slot>
70
+ <slot name="footer" slot="footer"></slot>
71
+ </ui-dialog>
72
+ </custom-element>
73
+
74
+ <custom-element name="ui-sheet-trigger" slot="trigger">
75
+ <style>
76
+ :host,
77
+ * {
78
+ touch-action: manipulation;
79
+ }
80
+ :host,
81
+ span {
82
+ display: contents;
83
+ }
84
+ </style>
85
+
86
+ <span part="trigger" onclick="showFrom(host)"><slot></slot></span>
87
+ </custom-element>
88
+
89
+ <custom-element name="ui-sheet-close">
90
+ <style>
91
+ :host,
92
+ * {
93
+ touch-action: manipulation;
94
+ }
95
+ :host,
96
+ span {
97
+ display: contents;
98
+ }
99
+ </style>
100
+
101
+ <span part="close" onclick="close()"><slot></slot></span>
102
+ </custom-element>
103
+
104
+ <custom-element name="ui-sheet-header" slot="header">
105
+ <style>
106
+ :host,
107
+ * {
108
+ touch-action: manipulation;
109
+ }
110
+ :host {
111
+ display: grid;
112
+ gap: calc(var(--spacing) * 2);
113
+ }
114
+ </style>
115
+
116
+ <slot></slot>
117
+ </custom-element>
118
+
119
+ <custom-element name="ui-sheet-title">
120
+ <style>
121
+ :host,
122
+ * {
123
+ touch-action: manipulation;
124
+ }
125
+ :host {
126
+ display: block;
127
+ }
128
+ h2 {
129
+ margin: 0;
130
+ font-size: var(--text-lg);
131
+ font-weight: var(--font-weight-semibold);
132
+ line-height: 1;
133
+ }
134
+ </style>
135
+
136
+ <h2 part="title"><slot></slot></h2>
137
+ </custom-element>
138
+
139
+ <custom-element name="ui-sheet-description">
140
+ <style>
141
+ :host,
142
+ * {
143
+ touch-action: manipulation;
144
+ }
145
+ :host {
146
+ display: block;
147
+ }
148
+ p {
149
+ margin: 0;
150
+ font-size: var(--text-sm);
151
+ color: var(--muted-foreground);
152
+ }
153
+ </style>
154
+
155
+ <p part="description"><slot></slot></p>
156
+ </custom-element>
157
+
158
+ <custom-element name="ui-sheet-footer" slot="footer">
159
+ <style>
160
+ :host,
161
+ * {
162
+ touch-action: manipulation;
163
+ }
164
+ :host {
165
+ display: flex;
166
+ flex-wrap: wrap;
167
+ justify-content: flex-end;
168
+ gap: calc(var(--spacing) * 2);
169
+ }
170
+ </style>
171
+
172
+ <slot></slot>
173
+ </custom-element>