shadcn_phlexcomponents 0.1.18 → 0.1.19

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 (128) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +321 -23
  3. data/app/javascript/controllers/accordion_controller.js +101 -90
  4. data/app/javascript/controllers/alert_dialog_controller.js +5 -4
  5. data/app/javascript/controllers/avatar_controller.js +12 -11
  6. data/app/javascript/controllers/checkbox_controller.js +26 -26
  7. data/app/javascript/controllers/collapsible_controller.js +35 -36
  8. data/app/javascript/controllers/combobox_controller.js +262 -231
  9. data/app/javascript/controllers/command_controller.js +205 -184
  10. data/app/javascript/controllers/date_picker_controller.js +252 -253
  11. data/app/javascript/controllers/date_range_picker_controller.js +189 -200
  12. data/app/javascript/controllers/dialog_controller.js +79 -78
  13. data/app/javascript/controllers/dropdown_menu_controller.js +229 -208
  14. data/app/javascript/controllers/dropdown_menu_sub_controller.js +111 -97
  15. data/app/javascript/controllers/form_field_controller.js +17 -16
  16. data/app/javascript/controllers/hover_card_controller.js +69 -71
  17. data/app/javascript/controllers/loading_button_controller.js +11 -10
  18. data/app/javascript/controllers/popover_controller.js +85 -78
  19. data/app/javascript/controllers/progress_controller.js +12 -11
  20. data/app/javascript/controllers/radio_group_controller.js +75 -74
  21. data/app/javascript/controllers/select_controller.js +247 -232
  22. data/app/javascript/controllers/sidebar_controller.js +26 -27
  23. data/app/javascript/controllers/sidebar_trigger_controller.js +12 -9
  24. data/app/javascript/controllers/slider_controller.js +74 -74
  25. data/app/javascript/controllers/switch_controller.js +23 -23
  26. data/app/javascript/controllers/tabs_controller.js +61 -61
  27. data/app/javascript/controllers/theme_switcher_controller.js +28 -27
  28. data/app/javascript/controllers/toast_container_controller.js +45 -31
  29. data/app/javascript/controllers/toast_controller.js +19 -18
  30. data/app/javascript/controllers/toggle_controller.js +17 -17
  31. data/app/javascript/controllers/toggle_group_controller.js +17 -17
  32. data/app/javascript/controllers/tooltip_controller.js +75 -77
  33. data/app/javascript/shadcn_phlexcomponents.js +27 -60
  34. data/app/javascript/utils/command.js +390 -334
  35. data/app/javascript/utils/floating_ui.js +139 -107
  36. data/app/javascript/utils/index.js +253 -190
  37. data/app/typescript/controllers/accordion_controller.ts +2 -0
  38. data/app/typescript/controllers/alert_dialog_controller.ts +2 -0
  39. data/app/typescript/controllers/avatar_controller.ts +2 -0
  40. data/app/typescript/controllers/checkbox_controller.ts +2 -0
  41. data/app/typescript/controllers/collapsible_controller.ts +2 -0
  42. data/app/typescript/controllers/combobox_controller.ts +2 -0
  43. data/app/typescript/controllers/command_controller.ts +2 -0
  44. data/app/typescript/controllers/date_picker_controller.ts +2 -0
  45. data/app/typescript/controllers/date_range_picker_controller.ts +2 -0
  46. data/app/typescript/controllers/dialog_controller.ts +2 -0
  47. data/app/typescript/controllers/dropdown_menu_controller.ts +2 -0
  48. data/app/typescript/controllers/dropdown_menu_sub_controller.ts +2 -0
  49. data/app/typescript/controllers/form_field_controller.ts +2 -0
  50. data/app/typescript/controllers/hover_card_controller.ts +2 -0
  51. data/app/typescript/controllers/loading_button_controller.ts +2 -0
  52. data/app/typescript/controllers/popover_controller.ts +2 -0
  53. data/app/typescript/controllers/progress_controller.ts +2 -0
  54. data/app/typescript/controllers/radio_group_controller.ts +2 -0
  55. data/app/typescript/controllers/select_controller.ts +2 -0
  56. data/app/typescript/controllers/slider_controller.ts +2 -0
  57. data/app/typescript/controllers/switch_controller.ts +2 -0
  58. data/app/typescript/controllers/tabs_controller.ts +2 -0
  59. data/app/typescript/controllers/theme_switcher_controller.ts +2 -0
  60. data/app/typescript/controllers/toast_container_controller.ts +2 -0
  61. data/app/typescript/controllers/toast_controller.ts +2 -0
  62. data/app/typescript/controllers/toggle_controller.ts +2 -0
  63. data/app/typescript/controllers/toggle_group_controller.ts +2 -0
  64. data/app/typescript/controllers/tooltip_controller.ts +2 -0
  65. data/app/typescript/shadcn_phlexcomponents.ts +27 -61
  66. data/app/typescript/utils/index.ts +7 -0
  67. data/lib/install/upgrade_shadcn_phlexcomponents.rb +28 -0
  68. data/lib/shadcn_phlexcomponents/components/accordion.rb +55 -12
  69. data/lib/shadcn_phlexcomponents/components/alert.rb +35 -16
  70. data/lib/shadcn_phlexcomponents/components/alert_dialog.rb +52 -12
  71. data/lib/shadcn_phlexcomponents/components/aspect_ratio.rb +33 -2
  72. data/lib/shadcn_phlexcomponents/components/avatar.rb +24 -7
  73. data/lib/shadcn_phlexcomponents/components/badge.rb +23 -18
  74. data/lib/shadcn_phlexcomponents/components/breadcrumb.rb +46 -6
  75. data/lib/shadcn_phlexcomponents/components/button.rb +32 -27
  76. data/lib/shadcn_phlexcomponents/components/card.rb +59 -10
  77. data/lib/shadcn_phlexcomponents/components/checkbox.rb +51 -30
  78. data/lib/shadcn_phlexcomponents/components/checkbox_group.rb +24 -4
  79. data/lib/shadcn_phlexcomponents/components/combobox.rb +212 -69
  80. data/lib/shadcn_phlexcomponents/components/command.rb +156 -52
  81. data/lib/shadcn_phlexcomponents/components/date_picker.rb +134 -48
  82. data/lib/shadcn_phlexcomponents/components/date_range_picker.rb +20 -42
  83. data/lib/shadcn_phlexcomponents/components/dialog.rb +80 -26
  84. data/lib/shadcn_phlexcomponents/components/dropdown_menu.rb +74 -25
  85. data/lib/shadcn_phlexcomponents/components/dropdown_menu_sub.rb +52 -24
  86. data/lib/shadcn_phlexcomponents/components/form/form_checkbox.rb +1 -1
  87. data/lib/shadcn_phlexcomponents/components/form/form_checkbox_group.rb +1 -1
  88. data/lib/shadcn_phlexcomponents/components/form/form_combobox.rb +1 -1
  89. data/lib/shadcn_phlexcomponents/components/form/form_date_picker.rb +1 -1
  90. data/lib/shadcn_phlexcomponents/components/form/form_date_range_picker.rb +1 -1
  91. data/lib/shadcn_phlexcomponents/components/form/form_error.rb +8 -1
  92. data/lib/shadcn_phlexcomponents/components/form/form_helpers.rb +3 -2
  93. data/lib/shadcn_phlexcomponents/components/form/form_hint.rb +8 -1
  94. data/lib/shadcn_phlexcomponents/components/form/form_input.rb +1 -1
  95. data/lib/shadcn_phlexcomponents/components/form/form_radio_group.rb +1 -1
  96. data/lib/shadcn_phlexcomponents/components/form/form_select.rb +1 -1
  97. data/lib/shadcn_phlexcomponents/components/form/form_slider.rb +1 -1
  98. data/lib/shadcn_phlexcomponents/components/form/form_switch.rb +1 -1
  99. data/lib/shadcn_phlexcomponents/components/form/form_textarea.rb +1 -1
  100. data/lib/shadcn_phlexcomponents/components/form.rb +22 -6
  101. data/lib/shadcn_phlexcomponents/components/hover_card.rb +48 -18
  102. data/lib/shadcn_phlexcomponents/components/input.rb +13 -8
  103. data/lib/shadcn_phlexcomponents/components/label.rb +9 -4
  104. data/lib/shadcn_phlexcomponents/components/link.rb +8 -1
  105. data/lib/shadcn_phlexcomponents/components/pagination.rb +34 -6
  106. data/lib/shadcn_phlexcomponents/components/popover.rb +43 -13
  107. data/lib/shadcn_phlexcomponents/components/progress.rb +37 -6
  108. data/lib/shadcn_phlexcomponents/components/radio_group.rb +41 -15
  109. data/lib/shadcn_phlexcomponents/components/select.rb +99 -42
  110. data/lib/shadcn_phlexcomponents/components/separator.rb +9 -4
  111. data/lib/shadcn_phlexcomponents/components/sheet.rb +87 -21
  112. data/lib/shadcn_phlexcomponents/components/skeleton.rb +8 -1
  113. data/lib/shadcn_phlexcomponents/components/switch.rb +45 -17
  114. data/lib/shadcn_phlexcomponents/components/table.rb +84 -17
  115. data/lib/shadcn_phlexcomponents/components/tabs.rb +36 -12
  116. data/lib/shadcn_phlexcomponents/components/textarea.rb +12 -7
  117. data/lib/shadcn_phlexcomponents/components/toast.rb +46 -20
  118. data/lib/shadcn_phlexcomponents/components/toast_container.rb +19 -14
  119. data/lib/shadcn_phlexcomponents/components/toggle.rb +28 -23
  120. data/lib/shadcn_phlexcomponents/components/tooltip.rb +49 -14
  121. data/lib/shadcn_phlexcomponents/configuration.rb +46 -0
  122. data/lib/shadcn_phlexcomponents/initializers/shadcn_phlexcomponents.rb +28 -0
  123. data/lib/shadcn_phlexcomponents/version.rb +1 -1
  124. data/lib/shadcn_phlexcomponents.rb +12 -1
  125. data/lib/tasks/upgrade.rake +10 -0
  126. metadata +15 -14
  127. data/app/typescript/controllers/sidebar_controller.ts +0 -39
  128. data/app/typescript/controllers/sidebar_trigger_controller.ts +0 -21
@@ -1,187 +1,208 @@
1
- import hotkeys from 'hotkeys-js';
2
- import { Controller } from '@hotwired/stimulus';
3
- import { showContent, hideContent, focusTrigger, ON_OPEN_FOCUS_DELAY, setGroupLabelsId, } from '../utils';
4
- import { scrollToItem, highlightItem, highlightItemByIndex, filteredItemsChanged, setItemsGroupId, search, clearRemoteResults, resetState, hideError, showList, } from '../utils/command';
5
- import { useDebounce, useClickOutside } from 'stimulus-use';
6
- import Fuse from 'fuse.js';
1
+ import hotkeys from "hotkeys-js";
2
+ import { Controller } from "@hotwired/stimulus";
3
+ import {
4
+ showContent,
5
+ hideContent,
6
+ focusTrigger,
7
+ ON_OPEN_FOCUS_DELAY,
8
+ setGroupLabelsId,
9
+ } from "../utils";
10
+ import {
11
+ scrollToItem,
12
+ highlightItem,
13
+ highlightItemByIndex,
14
+ filteredItemsChanged,
15
+ setItemsGroupId,
16
+ search,
17
+ clearRemoteResults,
18
+ resetState,
19
+ hideError,
20
+ showList,
21
+ } from "../utils/command";
22
+ import { useDebounce, useClickOutside } from "stimulus-use";
23
+ import Fuse from "fuse.js";
7
24
  const CommandController = class extends Controller {
8
- // targets
9
- static targets = [
10
- 'trigger',
11
- 'content',
12
- 'overlay',
13
- 'item',
14
- 'group',
15
- 'searchInput',
16
- 'list',
17
- 'listContainer',
18
- 'empty',
19
- 'modifierKey',
20
- 'loading',
21
- 'error',
22
- ];
23
- // values
24
- static values = {
25
- isOpen: Boolean,
26
- filteredItemIndexes: Array,
27
- searchUrl: String,
28
- };
29
- static debounces = ['search'];
30
- connect() {
31
- this.orderedItems = [...this.itemTargets];
32
- this.itemsInnerText = this.orderedItems.map((i) => i.innerText.trim());
33
- this.fuse = new Fuse(this.itemsInnerText);
34
- this.filteredItemIndexesValue = Array.from({ length: this.itemTargets.length }, (_, i) => i);
35
- this.isLoading = false;
36
- this.filteredItems = this.itemTargets;
37
- this.isDirty = false;
38
- this.searchPath = this.element.dataset.searchPath;
39
- setGroupLabelsId(this);
40
- setItemsGroupId(this);
41
- useDebounce(this);
42
- useClickOutside(this, { element: this.contentTarget, dispatchEvent: false });
43
- this.hotkeyListener = this.onHotkeyPressed.bind(this);
44
- this.DOMKeydownListener = this.onDOMKeydown.bind(this);
45
- this.setupHotkeys();
46
- this.replaceModifierKeyIcon();
47
- }
48
- open() {
49
- this.isOpenValue = true;
50
- this.highlightItemByIndex(0);
51
- setTimeout(() => {
52
- this.searchInputTarget.focus();
53
- }, ON_OPEN_FOCUS_DELAY);
54
- }
55
- close() {
56
- this.isOpenValue = false;
57
- resetState(this);
58
- }
59
- scrollToItem(index) {
60
- scrollToItem(this, index);
61
- }
62
- highlightItem(event = null, index = null) {
63
- highlightItem(this, event, index);
64
- }
65
- highlightItemByIndex(index) {
66
- highlightItemByIndex(this, index);
67
- }
68
- select(event) {
69
- let value = null;
70
- if (event instanceof KeyboardEvent) {
71
- const item = this.filteredItems.find((i) => i.dataset.highlighted === 'true');
72
- if (item) {
73
- value = item.dataset.value;
74
- }
75
- }
76
- else {
77
- // mouse event
78
- const item = event.currentTarget;
79
- value = item.dataset.value;
80
- }
81
- if (value) {
82
- window.Turbo.visit(value);
83
- this.close();
84
- }
85
- }
86
- inputKeydown(event) {
87
- if (event.key === ' ' && this.searchInputTarget.value.length === 0) {
88
- event.preventDefault();
89
- }
90
- hideError(this);
91
- showList(this);
92
- }
93
- search(event) {
94
- this.isDirty = true;
95
- clearRemoteResults(this);
96
- search(this, event);
97
- }
98
- clickOutside() {
99
- this.close();
100
- }
101
- isOpenValueChanged(isOpen, previousIsOpen) {
102
- if (isOpen) {
103
- showContent({
104
- trigger: this.triggerTarget,
105
- content: this.contentTarget,
106
- contentContainer: this.contentTarget,
107
- overlay: this.overlayTarget,
108
- });
109
- this.setupEventListeners();
110
- }
111
- else {
112
- hideContent({
113
- trigger: this.triggerTarget,
114
- content: this.contentTarget,
115
- contentContainer: this.contentTarget,
116
- overlay: this.overlayTarget,
117
- });
118
- if (previousIsOpen) {
119
- focusTrigger(this.triggerTarget);
120
- }
121
- this.cleanupEventListeners();
122
- }
123
- }
124
- filteredItemIndexesValueChanged(filteredItemIndexes) {
125
- filteredItemsChanged(this, filteredItemIndexes);
126
- }
127
- disconnect() {
128
- this.cleanupEventListeners();
129
- resetState(this);
130
- if (this.keybinds) {
131
- hotkeys.unbind(this.keybinds);
132
- }
133
- }
134
- setupHotkeys() {
135
- const modifierKey = this.element.dataset.modifierKey;
136
- const shortcutKey = this.element.dataset.shortcutKey;
137
- let keybinds = '';
138
- if (modifierKey && shortcutKey) {
139
- keybinds = `${modifierKey}+${shortcutKey}`;
140
- if (modifierKey === 'ctrl') {
141
- keybinds += `,cmd-${shortcutKey}`;
142
- }
143
- }
144
- else if (shortcutKey) {
145
- keybinds = shortcutKey;
146
- }
147
- this.keybinds = keybinds;
148
- hotkeys(keybinds, this.hotkeyListener);
149
- }
150
- onHotkeyPressed(event) {
151
- event.preventDefault();
152
- this.open();
153
- }
154
- replaceModifierKeyIcon() {
155
- if (this.hasModifierKeyTarget && this.isMac()) {
156
- this.modifierKeyTarget.innerHTML = '⌘';
157
- }
158
- }
159
- isMac() {
160
- const navigator = window.navigator;
161
- if (navigator.userAgentData) {
162
- return navigator.userAgentData.platform === 'macOS';
163
- }
164
- // Fallback to traditional methods
165
- return navigator.platform.toUpperCase().indexOf('MAC') >= 0;
166
- }
167
- onDOMKeydown(event) {
168
- if (!this.isOpenValue)
169
- return;
170
- const key = event.key;
171
- if (['Tab', 'Enter'].includes(key))
172
- event.preventDefault();
173
- if (key === 'Escape') {
174
- this.close();
175
- }
176
- }
177
- setupEventListeners() {
178
- document.addEventListener('keydown', this.DOMKeydownListener);
179
- }
180
- cleanupEventListeners() {
181
- document.removeEventListener('keydown', this.DOMKeydownListener);
182
- if (this.abortController) {
183
- this.abortController.abort();
184
- }
185
- }
25
+ static name = "command";
26
+ // targets
27
+ static targets = [
28
+ "trigger",
29
+ "content",
30
+ "overlay",
31
+ "item",
32
+ "group",
33
+ "searchInput",
34
+ "list",
35
+ "listContainer",
36
+ "empty",
37
+ "modifierKey",
38
+ "loading",
39
+ "error",
40
+ ];
41
+ // values
42
+ static values = {
43
+ isOpen: Boolean,
44
+ filteredItemIndexes: Array,
45
+ searchUrl: String,
46
+ };
47
+ static debounces = ["search"];
48
+ connect() {
49
+ this.orderedItems = [...this.itemTargets];
50
+ this.itemsInnerText = this.orderedItems.map((i) => i.innerText.trim());
51
+ this.fuse = new Fuse(this.itemsInnerText);
52
+ this.filteredItemIndexesValue = Array.from(
53
+ { length: this.itemTargets.length },
54
+ (_, i) => i,
55
+ );
56
+ this.isLoading = false;
57
+ this.filteredItems = this.itemTargets;
58
+ this.isDirty = false;
59
+ this.searchPath = this.element.dataset.searchPath;
60
+ setGroupLabelsId(this);
61
+ setItemsGroupId(this);
62
+ useDebounce(this);
63
+ useClickOutside(this, {
64
+ element: this.contentTarget,
65
+ dispatchEvent: false,
66
+ });
67
+ this.hotkeyListener = this.onHotkeyPressed.bind(this);
68
+ this.DOMKeydownListener = this.onDOMKeydown.bind(this);
69
+ this.setupHotkeys();
70
+ this.replaceModifierKeyIcon();
71
+ }
72
+ open() {
73
+ this.isOpenValue = true;
74
+ this.highlightItemByIndex(0);
75
+ setTimeout(() => {
76
+ this.searchInputTarget.focus();
77
+ }, ON_OPEN_FOCUS_DELAY);
78
+ }
79
+ close() {
80
+ this.isOpenValue = false;
81
+ resetState(this);
82
+ }
83
+ scrollToItem(index) {
84
+ scrollToItem(this, index);
85
+ }
86
+ highlightItem(event = null, index = null) {
87
+ highlightItem(this, event, index);
88
+ }
89
+ highlightItemByIndex(index) {
90
+ highlightItemByIndex(this, index);
91
+ }
92
+ select(event) {
93
+ let value = null;
94
+ if (event instanceof KeyboardEvent) {
95
+ const item = this.filteredItems.find(
96
+ (i) => i.dataset.highlighted === "true",
97
+ );
98
+ if (item) {
99
+ value = item.dataset.value;
100
+ }
101
+ } else {
102
+ // mouse event
103
+ const item = event.currentTarget;
104
+ value = item.dataset.value;
105
+ }
106
+ if (value) {
107
+ window.Turbo.visit(value);
108
+ this.close();
109
+ }
110
+ }
111
+ inputKeydown(event) {
112
+ if (event.key === " " && this.searchInputTarget.value.length === 0) {
113
+ event.preventDefault();
114
+ }
115
+ hideError(this);
116
+ showList(this);
117
+ }
118
+ search(event) {
119
+ this.isDirty = true;
120
+ clearRemoteResults(this);
121
+ search(this, event);
122
+ }
123
+ clickOutside() {
124
+ this.close();
125
+ }
126
+ isOpenValueChanged(isOpen, previousIsOpen) {
127
+ if (isOpen) {
128
+ showContent({
129
+ trigger: this.triggerTarget,
130
+ content: this.contentTarget,
131
+ contentContainer: this.contentTarget,
132
+ overlay: this.overlayTarget,
133
+ });
134
+ this.setupEventListeners();
135
+ } else {
136
+ hideContent({
137
+ trigger: this.triggerTarget,
138
+ content: this.contentTarget,
139
+ contentContainer: this.contentTarget,
140
+ overlay: this.overlayTarget,
141
+ });
142
+ if (previousIsOpen) {
143
+ focusTrigger(this.triggerTarget);
144
+ }
145
+ this.cleanupEventListeners();
146
+ }
147
+ }
148
+ filteredItemIndexesValueChanged(filteredItemIndexes) {
149
+ filteredItemsChanged(this, filteredItemIndexes);
150
+ }
151
+ disconnect() {
152
+ this.cleanupEventListeners();
153
+ resetState(this);
154
+ if (this.keybinds) {
155
+ hotkeys.unbind(this.keybinds);
156
+ }
157
+ }
158
+ setupHotkeys() {
159
+ const modifierKey = this.element.dataset.modifierKey;
160
+ const shortcutKey = this.element.dataset.shortcutKey;
161
+ let keybinds = "";
162
+ if (modifierKey && shortcutKey) {
163
+ keybinds = `${modifierKey}+${shortcutKey}`;
164
+ if (modifierKey === "ctrl") {
165
+ keybinds += `,cmd-${shortcutKey}`;
166
+ }
167
+ } else if (shortcutKey) {
168
+ keybinds = shortcutKey;
169
+ }
170
+ this.keybinds = keybinds;
171
+ hotkeys(keybinds, this.hotkeyListener);
172
+ }
173
+ onHotkeyPressed(event) {
174
+ event.preventDefault();
175
+ this.open();
176
+ }
177
+ replaceModifierKeyIcon() {
178
+ if (this.hasModifierKeyTarget && this.isMac()) {
179
+ this.modifierKeyTarget.innerHTML = "⌘";
180
+ }
181
+ }
182
+ isMac() {
183
+ const navigator = window.navigator;
184
+ if (navigator.userAgentData) {
185
+ return navigator.userAgentData.platform === "macOS";
186
+ }
187
+ // Fallback to traditional methods
188
+ return navigator.platform.toUpperCase().indexOf("MAC") >= 0;
189
+ }
190
+ onDOMKeydown(event) {
191
+ if (!this.isOpenValue) return;
192
+ const key = event.key;
193
+ if (["Tab", "Enter"].includes(key)) event.preventDefault();
194
+ if (key === "Escape") {
195
+ this.close();
196
+ }
197
+ }
198
+ setupEventListeners() {
199
+ document.addEventListener("keydown", this.DOMKeydownListener);
200
+ }
201
+ cleanupEventListeners() {
202
+ document.removeEventListener("keydown", this.DOMKeydownListener);
203
+ if (this.abortController) {
204
+ this.abortController.abort();
205
+ }
206
+ }
186
207
  };
187
208
  export { CommandController };