ariadne_view_components 0.0.50 → 0.0.51

Sign up to get free protection for your applications and to get access to all the features.
@@ -31,8 +31,8 @@ export default class OptionsController extends SyncedBooleanAttributesController
31
31
  readonly isMultiValue: boolean;
32
32
  readonly toggleableValue: boolean;
33
33
  optionTargetLookup: Map<Element, TOptionKey>;
34
- connect(): void;
35
34
  select(event: Event, updateTo?: TOutletChangeData<TActiveOptions>): void;
35
+ optionsTargetConnected(element: Element): void;
36
36
  getValueForElement(element: Element): boolean | null;
37
37
  getState(): TActiveOptions;
38
38
  outletUpdate: (event: Event, updateTo?: TOutletChangeData<TActiveOptions>) => void;
@@ -41,4 +41,5 @@ export default class SyncedBooleanAttributesController<T> extends OutletManagerC
41
41
  updateAttributesForElement(element: Element, value: boolean): void;
42
42
  syncElementAttributes(): void;
43
43
  validateAttrChange(dispatchEvent: TStimulusDispatchEvent<TSyncAttrDetail>): void;
44
+ doesElementHaveOnAttrs(element: Element): boolean;
44
45
  }
@@ -1,6 +1,8 @@
1
1
  <%= render Ariadne::BaseComponent.new(tag: @tag, classes: @classes, attributes: @attributes) do |component| %>
2
- <%= icon %>
3
- <%= title %>
2
+ <%= render Ariadne::LinkComponent.new(tag: @link_tag, href: @href, actionable: @actionable, classes: @link_classes, attributes: @link_attributes) do %>
3
+ <%= icon %>
4
+ <%= title %>
5
+ <% end %>
4
6
  <% if actions? %>
5
7
  <div class="<%= @actions_wrapper_classes %>">
6
8
  <% actions.each do |action| %>
@@ -1,27 +1,61 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Ariadne
4
- # Add a general description of component here
5
- # Add additional usage considerations or best practices that may aid the user to use the component correctly.
6
- # @accessibility Add any accessibility considerations
4
+ # Card of anchor tags (most likely) that are used to navigate around a similar idea
7
5
  class ActionCardComponent < Ariadne::Component
8
6
  DEFAULT_TAG = :div
7
+ DEFAULT_TITLE_TAG = :h3
8
+ DEFAULT_ICON_TAG = :svg
9
+ DEFAULT_ACTION_TAG = :a
9
10
  TAG_OPTIONS = [DEFAULT_TAG].freeze
10
11
 
11
12
  DEFAULT_CLASSES = {
12
- wrapper: "ariadne-w-fit ariadne-flex ariadne-flex-col ariadne-items-center",
13
- actions_wrapper: "ariadne-flex",
13
+ wrapper: "ariadne-overflow-hidden ariadne-w-96 ariadne-rounded-lg ariadne-mr-4 [&:last]:ariadne-mr-0",
14
+ actions_wrapper: "ariadne-flex ariadne-w-full",
15
+ icon: "",
16
+ link: "ariadne-flex ariadne-flex-col ariadne-items-center",
17
+ title: "ariadne-text-center ariadne-mb-4 ariadne-text-xl ariadne-font-bold",
18
+ action: "ariadne-w-full ariadne-flex ariadne-items-center ariadne-justify-center ariadne-py-6 ariadne-text-sm",
14
19
  }
15
20
 
16
21
  DEFAULT_ATTRIBUTES = {
17
22
  wrapper: {},
23
+ link: {},
24
+ icon: {},
25
+ title: {},
26
+ action: {},
18
27
  }
19
28
 
20
- renders_one :icon, Ariadne::HeroiconComponent
29
+ renders_one :icon, lambda { |tag: DEFAULT_ICON_TAG, icon: :inbox, size: :lg, variant: HeroiconsHelper::Icon::VARIANT_OUTLINE, classes: "", attributes: {}, text_classes: "", text_attributes: {}|
30
+ Ariadne::HeroiconComponent.new(
31
+ tag: tag,
32
+ size: size,
33
+ variant: variant,
34
+ classes: merge_class_names(DEFAULT_CLASSES[:icon], classes),
35
+ attributes: DEFAULT_ATTRIBUTES[:icon].merge(attributes),
36
+ text_classes: text_classes,
37
+ text_attributes: text_attributes,
38
+ icon: icon,
39
+ )
40
+ }
21
41
 
22
- renders_one :title, Ariadne::HeadingComponent
42
+ renders_one :title, lambda { |tag: DEFAULT_TITLE_TAG, classes: "", attributes: {}|
43
+ Ariadne::HeadingComponent.new(
44
+ tag: tag,
45
+ classes: merge_class_names(DEFAULT_CLASSES[:title], classes),
46
+ attributes: DEFAULT_ATTRIBUTES[:title].merge(attributes),
47
+ )
48
+ }
23
49
 
24
- renders_many :actions, Ariadne::ButtonComponent
50
+ renders_many :actions, lambda { |tag: DEFAULT_ACTION_TAG, href:, actionable: false, classes: "", attributes: {}|
51
+ Ariadne::LinkComponent.new(
52
+ tag: tag,
53
+ href: href,
54
+ actionable: actionable,
55
+ classes: merge_class_names(DEFAULT_CLASSES[:action], classes),
56
+ attributes: DEFAULT_ATTRIBUTES[:action].merge(attributes),
57
+ )
58
+ }
25
59
 
26
60
  # @example Default
27
61
  #
@@ -32,14 +66,23 @@ module Ariadne
32
66
  # @param attributes [Hash] <%= link_to_attributes_docs %>
33
67
  def initialize(
34
68
  tag: DEFAULT_TAG,
69
+ href:,
35
70
  classes: "",
36
71
  attributes: {},
37
- actions_wrapper_classes: ""
72
+ actions_wrapper_classes: "",
73
+ actionable: false,
74
+ link_classes: "",
75
+ link_attributes: {}
38
76
  )
39
77
  @tag = check_incoming_tag(DEFAULT_TAG, tag)
78
+ @href = href
40
79
  @classes = merge_class_names(DEFAULT_CLASSES[:wrapper], classes)
41
80
  @attributes = DEFAULT_ATTRIBUTES[:wrapper].merge(attributes)
42
81
  @actions_wrapper_classes = merge_class_names(DEFAULT_CLASSES[:actions_wrapper], actions_wrapper_classes)
82
+
83
+ @link_classes = merge_class_names(DEFAULT_CLASSES[:link], link_classes)
84
+ @link_attributes = DEFAULT_ATTRIBUTES[:link].merge(link_attributes)
85
+ @actionable = actionable
43
86
  end
44
87
  end
45
88
  end
@@ -59,7 +59,7 @@ module Ariadne
59
59
  "data-options-toggleable-value": toggleable_options,
60
60
  "data-toggleable-close-on-outside-click-value": close_on_outside_click,
61
61
  "data-toggleable-state-value": initially_open,
62
-
62
+ "aria-multiselectable": !single_selection,
63
63
  })
64
64
  .merge(attributes)
65
65
 
@@ -31,8 +31,8 @@ export default class OptionsController extends SyncedBooleanAttributesController
31
31
  readonly isMultiValue: boolean;
32
32
  readonly toggleableValue: boolean;
33
33
  optionTargetLookup: Map<Element, TOptionKey>;
34
- connect(): void;
35
34
  select(event: Event, updateTo?: TOutletChangeData<TActiveOptions>): void;
35
+ optionsTargetConnected(element: Element): void;
36
36
  getValueForElement(element: Element): boolean | null;
37
37
  getState(): TActiveOptions;
38
38
  outletUpdate: (event: Event, updateTo?: TOutletChangeData<TActiveOptions>) => void;
@@ -3,7 +3,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
3
3
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
4
4
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
5
5
  };
6
- var _OptionsController_instances, _OptionsController_shouldChangeState, _OptionsController_activateIndex, _OptionsController_deactivateIndex, _OptionsController_getElementKey, _OptionsController_buildActiveTargets;
6
+ var _OptionsController_instances, _OptionsController_shouldChangeState, _OptionsController_activateKey, _OptionsController_deactivateKey, _OptionsController_getElementKey;
7
7
  import SyncedBooleanAttributesController from '../synced_boolean_attributes_controller/synced_boolean_attributes_controller';
8
8
  class OptionsController extends SyncedBooleanAttributesController {
9
9
  constructor() {
@@ -12,10 +12,6 @@ class OptionsController extends SyncedBooleanAttributesController {
12
12
  this.optionTargetLookup = new Map();
13
13
  this.outletUpdate = this.select;
14
14
  }
15
- connect() {
16
- __classPrivateFieldGet(this, _OptionsController_instances, "m", _OptionsController_buildActiveTargets).call(this);
17
- this.syncElementAttributes();
18
- }
19
15
  select(event, updateTo = {}) {
20
16
  var _a;
21
17
  const activeOptions = updateTo.data;
@@ -30,11 +26,20 @@ class OptionsController extends SyncedBooleanAttributesController {
30
26
  if (shouldChangeState) {
31
27
  const willBeActive = !isCurrentlyActive;
32
28
  this.updateAttributesForElement(target, willBeActive);
33
- willBeActive ? __classPrivateFieldGet(this, _OptionsController_instances, "m", _OptionsController_activateIndex).call(this, optionKey) : __classPrivateFieldGet(this, _OptionsController_instances, "m", _OptionsController_deactivateIndex).call(this, optionKey);
29
+ willBeActive ? __classPrivateFieldGet(this, _OptionsController_instances, "m", _OptionsController_activateKey).call(this, optionKey) : __classPrivateFieldGet(this, _OptionsController_instances, "m", _OptionsController_deactivateKey).call(this, optionKey);
34
30
  }
35
31
  }
36
32
  this.sendToOutlets(event, Object.assign(Object.assign({}, updateTo), { data: this.activeOptionsValue }));
37
33
  }
34
+ optionsTargetConnected(element) {
35
+ const key = __classPrivateFieldGet(this, _OptionsController_instances, "m", _OptionsController_getElementKey).call(this, element);
36
+ if (this.doesElementHaveOnAttrs(element)) {
37
+ __classPrivateFieldGet(this, _OptionsController_instances, "m", _OptionsController_activateKey).call(this, key);
38
+ }
39
+ else {
40
+ __classPrivateFieldGet(this, _OptionsController_instances, "m", _OptionsController_deactivateKey).call(this, key);
41
+ }
42
+ }
38
43
  getValueForElement(element) {
39
44
  var _a;
40
45
  if (!this.optionTargetLookup.has(element)) {
@@ -64,9 +69,9 @@ _OptionsController_instances = new WeakSet(), _OptionsController_shouldChangeSta
64
69
  // Was selected and it's active but toggling behavior means it should deactivate
65
70
  // Was selected and it's not on, so it just needs to be turned on
66
71
  return true;
67
- }, _OptionsController_activateIndex = function _OptionsController_activateIndex(key) {
72
+ }, _OptionsController_activateKey = function _OptionsController_activateKey(key) {
68
73
  this.activeOptionsValue = Object.assign(Object.assign({}, this.activeOptionsValue), { [key]: true });
69
- }, _OptionsController_deactivateIndex = function _OptionsController_deactivateIndex(key) {
74
+ }, _OptionsController_deactivateKey = function _OptionsController_deactivateKey(key) {
70
75
  const copy = Object.assign({}, this.activeOptionsValue);
71
76
  delete copy[key];
72
77
  this.activeOptionsValue = copy;
@@ -76,21 +81,6 @@ _OptionsController_instances = new WeakSet(), _OptionsController_shouldChangeSta
76
81
  return elementValue;
77
82
  }
78
83
  return element.innerText.trim();
79
- }, _OptionsController_buildActiveTargets = function _OptionsController_buildActiveTargets() {
80
- this.optionTargetLookup = new Map();
81
- for (let index in this.optionTargets) {
82
- const target = this.optionTargets[index];
83
- const optionKey = __classPrivateFieldGet(this, _OptionsController_instances, "m", _OptionsController_getElementKey).call(this, target);
84
- this.optionTargetLookup.set(target, optionKey);
85
- const onSyncAttr = !!this.syncedAttrsValue.find(attr => target.getAttribute(attr) === 'true');
86
- if (onSyncAttr) {
87
- __classPrivateFieldGet(this, _OptionsController_instances, "m", _OptionsController_activateIndex).call(this, optionKey);
88
- }
89
- else {
90
- const hasOffAttr = !!this.antiAttrsValue.find(attr => target.getAttribute(attr) === 'false');
91
- hasOffAttr && __classPrivateFieldGet(this, _OptionsController_instances, "m", _OptionsController_activateIndex).call(this, optionKey);
92
- }
93
- }
94
84
  };
95
85
  OptionsController.outlets = SyncedBooleanAttributesController.outlets;
96
86
  OptionsController.targets = ['option'];
@@ -31,11 +31,6 @@ export default class OptionsController
31
31
 
32
32
  optionTargetLookup: Map<Element, TOptionKey> = new Map()
33
33
 
34
- connect(): void {
35
- this.#buildActiveTargets()
36
- this.syncElementAttributes()
37
- }
38
-
39
34
  select(event: Event, updateTo: TOutletChangeData<TActiveOptions> = {}) {
40
35
  const activeOptions = updateTo.data
41
36
  for (let index in this.optionTargets) {
@@ -51,13 +46,22 @@ export default class OptionsController
51
46
  if (shouldChangeState) {
52
47
  const willBeActive = !isCurrentlyActive
53
48
  this.updateAttributesForElement(target, willBeActive)
54
- willBeActive ? this.#activateIndex(optionKey) : this.#deactivateIndex(optionKey)
49
+ willBeActive ? this.#activateKey(optionKey) : this.#deactivateKey(optionKey)
55
50
  }
56
51
  }
57
52
 
58
53
  this.sendToOutlets(event, {...updateTo, data: this.activeOptionsValue})
59
54
  }
60
55
 
56
+ optionsTargetConnected(element: Element) {
57
+ const key = this.#getElementKey(element)
58
+ if (this.doesElementHaveOnAttrs(element)) {
59
+ this.#activateKey(key)
60
+ } else {
61
+ this.#deactivateKey(key)
62
+ }
63
+ }
64
+
61
65
  #shouldChangeState(isCurrentlyActive: boolean, wasSelected: boolean) {
62
66
  if (!wasSelected && !isCurrentlyActive) {
63
67
  // Not currently on and wasn't selected, no reason to change
@@ -80,11 +84,11 @@ export default class OptionsController
80
84
  return true
81
85
  }
82
86
 
83
- #activateIndex(key: TOptionKey) {
87
+ #activateKey(key: TOptionKey) {
84
88
  this.activeOptionsValue = {...this.activeOptionsValue, [key]: true}
85
89
  }
86
90
 
87
- #deactivateIndex(key: TOptionKey) {
91
+ #deactivateKey(key: TOptionKey) {
88
92
  const copy = {...this.activeOptionsValue}
89
93
  delete copy[key]
90
94
  this.activeOptionsValue = copy
@@ -99,22 +103,6 @@ export default class OptionsController
99
103
  return (element as HTMLElement).innerText.trim()
100
104
  }
101
105
 
102
- #buildActiveTargets() {
103
- this.optionTargetLookup = new Map()
104
- for (let index in this.optionTargets) {
105
- const target = this.optionTargets[index]
106
- const optionKey = this.#getElementKey(target)
107
- this.optionTargetLookup.set(target, optionKey)
108
- const onSyncAttr = !!this.syncedAttrsValue.find(attr => target.getAttribute(attr) === 'true')
109
- if (onSyncAttr) {
110
- this.#activateIndex(optionKey)
111
- } else {
112
- const hasOffAttr = !!this.antiAttrsValue.find(attr => target.getAttribute(attr) === 'false')
113
- hasOffAttr && this.#activateIndex(optionKey)
114
- }
115
- }
116
- }
117
-
118
106
  getValueForElement(element: Element) {
119
107
  if (!this.optionTargetLookup.has(element)) {
120
108
  return null
@@ -41,4 +41,5 @@ export default class SyncedBooleanAttributesController<T> extends OutletManagerC
41
41
  updateAttributesForElement(element: Element, value: boolean): void;
42
42
  syncElementAttributes(): void;
43
43
  validateAttrChange(dispatchEvent: TStimulusDispatchEvent<TSyncAttrDetail>): void;
44
+ doesElementHaveOnAttrs(element: Element): boolean;
44
45
  }
@@ -95,6 +95,26 @@ class SyncedBooleanAttributesController extends OutletManagerController {
95
95
  }
96
96
  }
97
97
  }
98
+ doesElementHaveOnAttrs(element) {
99
+ if (this.hasSyncedAttrsValue) {
100
+ for (let i = 0; i < this.syncedAttrsValue.length; i++) {
101
+ const attrName = this.syncedAttrsValue[i];
102
+ if (element.getAttribute(attrName) === 'true') {
103
+ return true;
104
+ }
105
+ }
106
+ }
107
+ if (this.hasAntiAttrsValue) {
108
+ for (let i = 0; i < this.antiAttrsValue.length; i++) {
109
+ const attrName = this.antiAttrsValue[i];
110
+ const attrValue = element.getAttribute(attrName);
111
+ if (attrValue === 'false' || (SyncedBooleanAttributesController.removeOnFalseAttrs[attrName] && !attrValue)) {
112
+ return true;
113
+ }
114
+ }
115
+ }
116
+ return false;
117
+ }
98
118
  }
99
119
  _SyncedBooleanAttributesController_instances = new WeakSet(), _SyncedBooleanAttributesController_isSyncedAttr = function _SyncedBooleanAttributesController_isSyncedAttr(attr) {
100
120
  var _a;
@@ -131,6 +131,29 @@ export default class SyncedBooleanAttributesController<T> extends OutletManagerC
131
131
  }
132
132
  }
133
133
 
134
+ doesElementHaveOnAttrs(element: Element) {
135
+ if (this.hasSyncedAttrsValue) {
136
+ for (let i = 0; i < this.syncedAttrsValue.length; i++) {
137
+ const attrName = this.syncedAttrsValue[i]
138
+ if (element.getAttribute(attrName) === 'true') {
139
+ return true
140
+ }
141
+ }
142
+ }
143
+
144
+ if (this.hasAntiAttrsValue) {
145
+ for (let i = 0; i < this.antiAttrsValue.length; i++) {
146
+ const attrName = this.antiAttrsValue[i]
147
+ const attrValue = element.getAttribute(attrName)
148
+ if (attrValue === 'false' || (SyncedBooleanAttributesController.removeOnFalseAttrs[attrName] && !attrValue)) {
149
+ return true
150
+ }
151
+ }
152
+ }
153
+
154
+ return false
155
+ }
156
+
134
157
  #isSyncedAttr(attr: string) {
135
158
  // Helper function to determine if the attr is synced
136
159
  if (this.syncedAttrsLookup === null) {
@@ -3,6 +3,6 @@
3
3
  # :nocov:
4
4
  module Ariadne
5
5
  module ViewComponents
6
- VERSION = "0.0.50"
6
+ VERSION = "0.0.51"
7
7
  end
8
8
  end
@@ -1,14 +1,29 @@
1
1
  {
2
2
  "Ariadne::ActionCardComponent": {
3
+ "DEFAULT_ACTION_TAG": "a",
3
4
  "DEFAULT_ATTRIBUTES": {
4
5
  "wrapper": {
6
+ },
7
+ "link": {
8
+ },
9
+ "icon": {
10
+ },
11
+ "title": {
12
+ },
13
+ "action": {
5
14
  }
6
15
  },
7
16
  "DEFAULT_CLASSES": {
8
- "wrapper": "ariadne-w-fit ariadne-flex ariadne-flex-col ariadne-items-center",
9
- "actions_wrapper": "ariadne-flex"
10
- },
17
+ "wrapper": "ariadne-overflow-hidden ariadne-w-96 ariadne-rounded-lg ariadne-mr-4 [&:last]:ariadne-mr-0",
18
+ "actions_wrapper": "ariadne-flex ariadne-w-full",
19
+ "icon": "",
20
+ "link": "ariadne-flex ariadne-flex-col ariadne-items-center",
21
+ "title": "ariadne-text-center ariadne-mb-4 ariadne-text-xl ariadne-font-bold",
22
+ "action": "ariadne-w-full ariadne-flex ariadne-items-center ariadne-justify-center ariadne-py-6 ariadne-text-sm"
23
+ },
24
+ "DEFAULT_ICON_TAG": "svg",
11
25
  "DEFAULT_TAG": "div",
26
+ "DEFAULT_TITLE_TAG": "h3",
12
27
  "TAG_OPTIONS": [
13
28
  "div"
14
29
  ]
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ariadne_view_components
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.50
4
+ version: 0.0.51
5
5
  platform: ruby
6
6
  authors:
7
7
  - Garen J. Torikian
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-06-29 00:00:00.000000000 Z
11
+ date: 2023-06-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: tailwind_merge