ariadne_view_components 0.0.48-x64-mingw-ucrt → 0.0.50-x64-mingw-ucrt

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/app/assets/builds/ariadne_view_components.css +2178 -0
  4. data/app/assets/javascripts/ariadne_view_components.js +2 -2
  5. data/app/assets/javascripts/ariadne_view_components.js.map +1 -1
  6. data/app/assets/javascripts/components/ariadne/events_controller/events_controller.d.ts +4 -0
  7. data/app/assets/javascripts/components/ariadne/options_controller/options_controller.d.ts +30 -11
  8. data/app/assets/javascripts/components/ariadne/outlet_manager_controller/outlet_manager_controller.d.ts +42 -0
  9. data/app/assets/javascripts/components/ariadne/string_match_controller/string_match_controller.d.ts +27 -0
  10. data/app/assets/javascripts/components/ariadne/synced_boolean_attributes_controller/synced_boolean_attributes_controller.d.ts +44 -0
  11. data/app/assets/javascripts/components/ariadne/toggleable_controller/toggleable_controller.d.ts +17 -17
  12. data/app/components/ariadne/ariadne.js +4 -0
  13. data/app/components/ariadne/ariadne.ts +4 -0
  14. data/app/components/ariadne/close_button_component.html.erb +1 -1
  15. data/app/components/ariadne/close_button_component.rb +2 -1
  16. data/app/components/ariadne/combobox_component.html.erb +14 -0
  17. data/app/components/ariadne/combobox_component.rb +76 -0
  18. data/app/components/ariadne/events_controller/events_controller.d.ts +4 -0
  19. data/app/components/ariadne/events_controller/events_controller.js +6 -0
  20. data/app/components/ariadne/events_controller/events_controller.ts +7 -0
  21. data/app/components/ariadne/layout_component.html.erb +21 -0
  22. data/app/components/ariadne/layout_component.rb +69 -0
  23. data/app/components/ariadne/modal_component.html.erb +11 -0
  24. data/app/components/ariadne/modal_component.rb +88 -0
  25. data/app/components/ariadne/options_controller/options_controller.d.ts +30 -11
  26. data/app/components/ariadne/options_controller/options_controller.js +75 -27
  27. data/app/components/ariadne/options_controller/options_controller.ts +104 -29
  28. data/app/components/ariadne/outlet_manager_controller/outlet_manager_controller.d.ts +42 -0
  29. data/app/components/ariadne/outlet_manager_controller/outlet_manager_controller.js +237 -0
  30. data/app/components/ariadne/outlet_manager_controller/outlet_manager_controller.ts +278 -0
  31. data/app/components/ariadne/popover_component.html.erb +0 -1
  32. data/app/components/ariadne/show_more_button_component.html.erb +1 -1
  33. data/app/components/ariadne/string_match_controller/string_match_controller.d.ts +27 -0
  34. data/app/components/ariadne/string_match_controller/string_match_controller.js +51 -0
  35. data/app/components/ariadne/string_match_controller/string_match_controller.ts +64 -0
  36. data/app/components/ariadne/synced_boolean_attributes_controller/synced_boolean_attributes_controller.d.ts +44 -0
  37. data/app/components/ariadne/synced_boolean_attributes_controller/synced_boolean_attributes_controller.js +153 -0
  38. data/app/components/ariadne/synced_boolean_attributes_controller/synced_boolean_attributes_controller.ts +192 -0
  39. data/app/components/ariadne/toggleable_controller/toggleable_controller.d.ts +17 -17
  40. data/app/components/ariadne/toggleable_controller/toggleable_controller.js +35 -55
  41. data/app/components/ariadne/toggleable_controller/toggleable_controller.ts +41 -51
  42. data/lib/ariadne/view_components/version.rb +1 -1
  43. data/static/audited_at.json +3 -0
  44. data/static/constants.json +74 -0
  45. data/static/statuses.json +3 -0
  46. metadata +26 -3
@@ -0,0 +1,4 @@
1
+ import { Controller } from '@hotwired/stimulus';
2
+ export default class EventsController extends Controller {
3
+ stopPropagation(e: Event): void;
4
+ }
@@ -1,21 +1,40 @@
1
- import { Controller } from '@hotwired/stimulus';
2
- export default class OptionsController extends Controller {
1
+ import { TOutletChangeData } from '../outlet_manager_controller/outlet_manager_controller';
2
+ import SyncedBooleanAttributesController from '../synced_boolean_attributes_controller/synced_boolean_attributes_controller';
3
+ type TOptionKey = string | number;
4
+ type TActiveOptions = {
5
+ [k: TOptionKey]: boolean;
6
+ };
7
+ export interface OptionsOutlet extends SyncedBooleanAttributesController<TActiveOptions> {
8
+ select: (e: Event, updateTo?: TOutletChangeData<TActiveOptions>) => void;
9
+ }
10
+ export default class OptionsController extends SyncedBooleanAttributesController<TActiveOptions> implements OptionsOutlet {
3
11
  #private;
12
+ static outlets: string[];
4
13
  static targets: string[];
5
14
  static values: {
6
- activeIndex: {
7
- type: NumberConstructor;
8
- default: number;
15
+ activeOptions: ObjectConstructor;
16
+ isMulti: {
17
+ type: BooleanConstructor;
18
+ default: boolean;
19
+ };
20
+ toggleable: {
21
+ type: BooleanConstructor;
22
+ default: boolean;
9
23
  };
10
24
  syncedAttrs: ArrayConstructor;
11
25
  antiAttrs: ArrayConstructor;
26
+ protectAttrs: BooleanConstructor;
27
+ outletEvents: ArrayConstructor;
12
28
  };
13
29
  readonly optionTargets: Array<Element>;
14
- activeIndexValue: number;
15
- readonly syncedAttrsValue: string[];
16
- readonly hasSyncedAttrsValue: boolean;
17
- readonly antiAttrsValue: string[];
18
- readonly hasAntiAttrsValue: boolean;
30
+ activeOptionsValue: TActiveOptions;
31
+ readonly isMultiValue: boolean;
32
+ readonly toggleableValue: boolean;
33
+ optionTargetLookup: Map<Element, TOptionKey>;
19
34
  connect(): void;
20
- select(e: Event, newIndex?: number): void;
35
+ select(event: Event, updateTo?: TOutletChangeData<TActiveOptions>): void;
36
+ getValueForElement(element: Element): boolean | null;
37
+ getState(): TActiveOptions;
38
+ outletUpdate: (event: Event, updateTo?: TOutletChangeData<TActiveOptions>) => void;
21
39
  }
40
+ export {};
@@ -0,0 +1,42 @@
1
+ import { Controller } from '@hotwired/stimulus';
2
+ type TOutletEventLookup = boolean | {
3
+ [k: string]: TOutletEventLookup;
4
+ };
5
+ export type TOutletChangeData<T> = {
6
+ eventKey?: string;
7
+ data?: T;
8
+ } | undefined;
9
+ export default class OutletManagerController<T> extends Controller {
10
+ #private;
11
+ static values: {
12
+ outletEvents: ArrayConstructor;
13
+ };
14
+ readonly outletEventsValue: Array<string>;
15
+ readonly hasOutletEventsValue: boolean;
16
+ static outlets: string[];
17
+ readonly toggleableOutlets: Array<OutletManagerController<T>>;
18
+ readonly hasToggleableOutlet: boolean;
19
+ readonly optionsOutlets: Array<OutletManagerController<T>>;
20
+ readonly hasOptionsOutlet: boolean;
21
+ readonly stringMatchOutlets: Array<OutletManagerController<T>>;
22
+ readonly hasStringMatchOutlet: boolean;
23
+ outletEventsLookup: TOutletEventLookup | null;
24
+ static domEvents: {
25
+ [k: string]: boolean;
26
+ };
27
+ eventRecords: Map<Event, boolean>;
28
+ getOutlets(): Array<OutletManagerController<T>> | null | void;
29
+ outletUpdate(event: Event, data: TOutletChangeData<T>): void;
30
+ getState(): T;
31
+ connect(): void;
32
+ syncOutlets(): void;
33
+ sendToOutlets(event: Event, updateTo?: TOutletChangeData<T>): void;
34
+ isListeningForOutletEvent(eventTypes: string): boolean;
35
+ isDOMEventName(eventName: string): boolean;
36
+ getEventKey(event: Event): string;
37
+ hasHeardEvent(event: Event): boolean;
38
+ get event_key_prefix(): string;
39
+ get event_key_postfix(): string;
40
+ get outletEvents(): TOutletEventLookup;
41
+ }
42
+ export {};
@@ -0,0 +1,27 @@
1
+ import { TOutletChangeData } from '../outlet_manager_controller/outlet_manager_controller';
2
+ import SyncedBooleanAttributesController from '../synced_boolean_attributes_controller/synced_boolean_attributes_controller';
3
+ export interface StringMatchOutlet extends SyncedBooleanAttributesController<string> {
4
+ change: (event: Event, updateTo?: TOutletChangeData<string>) => void;
5
+ }
6
+ export default class StringMatchController extends SyncedBooleanAttributesController<string> implements StringMatchOutlet {
7
+ #private;
8
+ static outlets: string[];
9
+ static targets: string[];
10
+ static values: {
11
+ keyword: StringConstructor;
12
+ syncedAttrs: ArrayConstructor;
13
+ antiAttrs: ArrayConstructor;
14
+ protectAttrs: BooleanConstructor;
15
+ outletEvents: ArrayConstructor;
16
+ };
17
+ readonly matchTargets: Array<HTMLElement>;
18
+ readonly hasMatchTarget: boolean;
19
+ readonly emptyTarget: Element;
20
+ readonly hasEmptyTarget: boolean;
21
+ keywordValue: string;
22
+ change(event: Event, updateTo?: TOutletChangeData<string>): void;
23
+ getElementsToSync(): Element[] | null | undefined;
24
+ getValueForElement(element: Element): boolean;
25
+ getState(): string;
26
+ outletUpdate: (event: Event, updateTo?: TOutletChangeData<string>) => void;
27
+ }
@@ -0,0 +1,44 @@
1
+ import OutletManagerController from '../outlet_manager_controller/outlet_manager_controller';
2
+ export type TStimulusDispatchEvent<TDetails> = {
3
+ target?: Element | undefined;
4
+ detail?: TDetails | undefined;
5
+ prefix?: string | undefined;
6
+ bubbles?: boolean | undefined;
7
+ cancelable?: boolean | undefined;
8
+ preventDefault: () => void;
9
+ };
10
+ export type TBooleanValueDetail = {
11
+ value: boolean;
12
+ };
13
+ export interface TSyncAttrDetail extends TBooleanValueDetail {
14
+ attr: string;
15
+ }
16
+ export default class SyncedBooleanAttributesController<T> extends OutletManagerController<T> {
17
+ #private;
18
+ static values: {
19
+ syncedAttrs: ArrayConstructor;
20
+ antiAttrs: ArrayConstructor;
21
+ protectAttrs: BooleanConstructor;
22
+ outletEvents: ArrayConstructor;
23
+ };
24
+ readonly syncedAttrsValue: string[];
25
+ readonly hasSyncedAttrsValue: boolean;
26
+ readonly antiAttrsValue: string[];
27
+ readonly hasAntiAttrsValue: boolean;
28
+ readonly protectAttrsValue: boolean;
29
+ static removeOnFalseAttrs: {
30
+ [k: string]: boolean;
31
+ };
32
+ syncedAttrsLookup: {
33
+ [k: string]: boolean;
34
+ } | null;
35
+ antiAttrsLookup: {
36
+ [k: string]: boolean;
37
+ } | null;
38
+ getValueForElement(element: Element): boolean | null;
39
+ getElementsToSync(): Array<Element> | null | undefined;
40
+ connect(): void;
41
+ updateAttributesForElement(element: Element, value: boolean): void;
42
+ syncElementAttributes(): void;
43
+ validateAttrChange(dispatchEvent: TStimulusDispatchEvent<TSyncAttrDetail>): void;
44
+ }
@@ -1,34 +1,34 @@
1
- import { Controller } from '@hotwired/stimulus';
2
- export interface ToggleableOutlet {
3
- toggle: (event: Event, value?: boolean) => void;
1
+ import type { TOutletChangeData } from '../outlet_manager_controller/outlet_manager_controller';
2
+ import SyncedBooleanAttributesController from '../synced_boolean_attributes_controller/synced_boolean_attributes_controller';
3
+ export interface ToggleableOutlet extends SyncedBooleanAttributesController<boolean> {
4
+ toggle: (event: Event, updateTo?: TOutletChangeData<boolean>) => void;
4
5
  }
5
- export default class ToggleableController extends Controller implements ToggleableOutlet {
6
- #private;
6
+ export default class ToggleableController extends SyncedBooleanAttributesController<boolean> implements ToggleableOutlet {
7
7
  static outlets: string[];
8
8
  static values: {
9
9
  state: {
10
10
  type: BooleanConstructor;
11
11
  default: boolean;
12
12
  };
13
- syncedAttrs: ArrayConstructor;
14
- antiAttrs: ArrayConstructor;
15
13
  closeOnOutsideClick: {
16
14
  type: BooleanConstructor;
17
15
  default: boolean;
18
16
  };
19
- };
20
- static removeOnFalseAttrs: {
21
- [k: string]: boolean;
17
+ syncedAttrs: ArrayConstructor;
18
+ antiAttrs: ArrayConstructor;
19
+ protectAttrs: BooleanConstructor;
20
+ outletEvents: ArrayConstructor;
22
21
  };
23
22
  stateValue: boolean;
24
- readonly toggleableOutlets: Array<ToggleableOutlet>;
25
- readonly hasToggleableOutlet: boolean;
26
- readonly syncedAttrsValue: string[];
27
- readonly hasSyncedAttrsValue: boolean;
28
- readonly antiAttrsValue: string[];
29
- readonly hasAntiAttrsValue: boolean;
30
23
  readonly closeOnOutsideClickValue: boolean;
31
24
  connect(): void;
32
- toggle(event: Event, value?: boolean): void;
25
+ toggle(event: Event, updateTo?: TOutletChangeData<boolean>): void;
26
+ on(event: Event): void;
27
+ off(event: Event): void;
33
28
  clickOutside(event: Event): void;
29
+ getValueForElement(element: Element): boolean | null;
30
+ getElementsToSync(): Element[] | null | undefined;
31
+ getState(): boolean;
32
+ get event_key_postfix(): "on" | "off";
33
+ outletUpdate: (event: Event, updateTo?: TOutletChangeData<boolean>) => void;
34
34
  }
@@ -1,5 +1,7 @@
1
1
  import { Application } from '@hotwired/stimulus';
2
2
  import AriadneForm from './ariadne-form';
3
+ import StringMatchController from './string_match_controller/string_match_controller';
4
+ import EventsController from './events_controller/events_controller';
3
5
  import OptionsController from './options_controller/options_controller';
4
6
  import AccumulatorController from './accumulator_controller/accumulator_controller';
5
7
  import ToggleableController from './toggleable_controller/toggleable_controller';
@@ -20,3 +22,5 @@ application.register('tooltip-component', TooltipComponent);
20
22
  application.register('toggleable', ToggleableController);
21
23
  application.register('accumulator', AccumulatorController);
22
24
  application.register('options', OptionsController);
25
+ application.register('string-match', StringMatchController);
26
+ application.register('events', EventsController);
@@ -2,6 +2,8 @@ import {Application} from '@hotwired/stimulus'
2
2
 
3
3
  import AriadneForm from './ariadne-form'
4
4
 
5
+ import StringMatchController from './string_match_controller/string_match_controller'
6
+ import EventsController from './events_controller/events_controller'
5
7
  import OptionsController from './options_controller/options_controller'
6
8
  import AccumulatorController from './accumulator_controller/accumulator_controller'
7
9
  import ToggleableController from './toggleable_controller/toggleable_controller'
@@ -25,3 +27,5 @@ application.register('tooltip-component', TooltipComponent)
25
27
  application.register('toggleable', ToggleableController)
26
28
  application.register('accumulator', AccumulatorController)
27
29
  application.register('options', OptionsController)
30
+ application.register('string-match', StringMatchController)
31
+ application.register('events', EventsController)
@@ -1,4 +1,4 @@
1
- <%= render Ariadne::ButtonComponent.new(tag: @tag, classes: @classes, attributes: @attributes) do |component| %>
1
+ <%= render Ariadne::ButtonComponent.new(tag: @tag, classes: @classes, scheme: @scheme, attributes: @attributes) do |component| %>
2
2
  <%= render Ariadne::HeroiconComponent.new(icon: "x-mark", variant: HeroiconsHelper::Icon::VARIANT_OUTLINE, classes: @icon_classes, size: @size) do |icon| %>
3
3
  <% end %>
4
4
  <% end %>
@@ -15,7 +15,7 @@ module Ariadne
15
15
  # @param tag [Symbol, String] The rendered tag name.
16
16
  # @param classes [String] <%= link_to_classes_docs %>
17
17
  # @param attributes [Hash] <%= link_to_attributes_docs %>
18
- def initialize(tag: DEFAULT_TAG, classes: "", icon_classes: "", size: :xs, aria_label: nil, attributes: {})
18
+ def initialize(tag: DEFAULT_TAG, classes: "", icon_classes: "", size: :xs, aria_label: nil, scheme: :none, attributes: {})
19
19
  raise ArgumentError, "An 'aria_label' argument is required to use a Close Button. Include as much detail as you can about what the button will be closing." if aria_label.blank?
20
20
 
21
21
  @tag = check_incoming_tag(DEFAULT_TAG, tag)
@@ -25,6 +25,7 @@ module Ariadne
25
25
  classes,
26
26
  )
27
27
 
28
+ @scheme = scheme
28
29
  @size = size
29
30
  @icon_classses = icon_classes
30
31
  end
@@ -0,0 +1,14 @@
1
+ <%= render Ariadne::BaseComponent.new(tag: @tag, classes: @classes, attributes: @attributes) do %>
2
+ <%= render Ariadne::BaseComponent.new(tag: :input, classes: @input_classes, attributes: @input_attributes) do %>
3
+ <% if icon? %>
4
+ <%= icon %>
5
+ <% else %>
6
+ <%= Ariadne::HeroiconComponent.new(icon: :cube, variant: HeroiconsHelper::Icon::VARIANT_OUTLINE) %>
7
+ <% end %>
8
+ <% end %>
9
+ <%= render Ariadne::BaseComponent.new(tag: @options_wrapper_tag, classes: @options_wrapper_classes, attributes: @options_wrapper_attributes) do %>
10
+ <% options.each do |option| %>
11
+ <%= option %>
12
+ <% end %>
13
+ <% end %>
14
+ <% end %>
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ariadne
4
+ # Input with a dropdown selection
5
+ class ComboboxComponent < Ariadne::Component
6
+ DEFAULT_TAG = :div
7
+ DEFAULT_OPTIONS_WRAPPER_TAG = :div
8
+ TAG_OPTIONS = [DEFAULT_TAG].freeze
9
+
10
+ DEFAULT_CLASSES = {
11
+ wrapper: "ariadne-group ariadne-w-fit ariadne-relative",
12
+ options_wrapper: "group-data-[toggleable-state-value=false]:ariadne-hidden ariadne-absolute ariadne-w-full ariadne-z-10",
13
+ input: "",
14
+ }
15
+
16
+ DEFAULT_ATTRIBUTES = {
17
+ wrapper: {
18
+ "data-controller": "options toggleable string-match",
19
+ },
20
+ options_wrapper: {},
21
+ input: {
22
+ type: "text",
23
+ autocomplete: "off",
24
+ "data-action": "input->string-match#change focusin->toggleable#on",
25
+ },
26
+ }
27
+
28
+ renders_many :options
29
+
30
+ renders_one :icon, Ariadne::HeroiconComponent
31
+
32
+ # @example Default
33
+ #
34
+ # <%= render(Ariadne::ComboboxComponent.new) { "Example" } %>
35
+ #
36
+ # @param tag [Symbol, String] The rendered tag name.
37
+ # @param classes [String] <%= link_to_classes_docs %>
38
+ # @param attributes [Hash] <%= link_to_attributes_docs %>
39
+ def initialize(
40
+ tag: DEFAULT_TAG,
41
+ classes: "",
42
+ attributes: {},
43
+ options_tag: DEFAULT_OPTIONS_WRAPPER_TAG,
44
+ options_wrapper_classes: "",
45
+ options_wrapper_attributes: {},
46
+ close_on_outside_click: true,
47
+ close_on_select: false,
48
+ initially_open: false,
49
+ single_selection: false,
50
+ toggleable_options: true, # Do options unselect if clicked a second time
51
+ input_classes: "",
52
+ input_attributes: {}
53
+ )
54
+ @tag = check_incoming_tag(DEFAULT_TAG, tag)
55
+ @classes = merge_class_names(DEFAULT_CLASSES[:wrapper], classes)
56
+ @attributes = DEFAULT_ATTRIBUTES[:wrapper]
57
+ .merge({
58
+ "data-options-is-multi-value": !single_selection,
59
+ "data-options-toggleable-value": toggleable_options,
60
+ "data-toggleable-close-on-outside-click-value": close_on_outside_click,
61
+ "data-toggleable-state-value": initially_open,
62
+
63
+ })
64
+ .merge(attributes)
65
+
66
+ @input_classes = merge_class_names(DEFAULT_CLASSES[:input], input_classes)
67
+ @input_attributes = DEFAULT_ATTRIBUTES[:input].merge(input_attributes)
68
+
69
+ @options_wrapper_tag = check_incoming_tag(DEFAULT_OPTIONS_WRAPPER_TAG, options_tag)
70
+ @options_wrapper_classes = merge_class_names(DEFAULT_CLASSES[:options_wrapper], options_wrapper_classes)
71
+ @options_wrapper_attributes = DEFAULT_ATTRIBUTES[:options_wrapper]
72
+ .merge({ "data-action": close_on_select ? "click->toggleable#off" : "" })
73
+ .merge(options_wrapper_attributes)
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,4 @@
1
+ import { Controller } from '@hotwired/stimulus';
2
+ export default class EventsController extends Controller {
3
+ stopPropagation(e: Event): void;
4
+ }
@@ -0,0 +1,6 @@
1
+ import { Controller } from '@hotwired/stimulus';
2
+ export default class EventsController extends Controller {
3
+ stopPropagation(e) {
4
+ e.stopPropagation();
5
+ }
6
+ }
@@ -0,0 +1,7 @@
1
+ import {Controller} from '@hotwired/stimulus'
2
+
3
+ export default class EventsController extends Controller {
4
+ stopPropagation(e: Event) {
5
+ e.stopPropagation()
6
+ }
7
+ }
@@ -0,0 +1,21 @@
1
+ <%= render Ariadne::BaseComponent.new(tag: @tag, classes: @classes, attributes: @attributes) do %>
2
+ <% if sidecars? %>
3
+ <%= render Ariadne::BaseComponent.new(tag: @sidecar_tag, classes: @sidecar_classes, attributes: @sidecar_attributes) do %>
4
+ <% sidecars.each do |sidecar| %>
5
+ <%= sidecar %>
6
+ <% end %>
7
+ <% end %>
8
+ <% end %>
9
+ <%= render Ariadne::BaseComponent.new(tag: @main_tag, classes: @main_classes, attributes: @main_attributes) do %>
10
+ <% mains.each do |main| %>
11
+ <%= main %>
12
+ <% end %>
13
+ <% end %>
14
+ <% if asides? %>
15
+ <%= render Ariadne::BaseComponent.new(tag: @aside_tag, classes: @aside_classes, attributes: @aside_attributes) do %>
16
+ <% asides.each do |aside| %>
17
+ <%= aside %>
18
+ <% end %>
19
+ <% end %>
20
+ <% end %>
21
+ <% end %>
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ariadne
4
+ # Layout component to control the widths of 1-3 columns
5
+ class LayoutComponent < Ariadne::Component
6
+ DEFAULT_TAG = :div
7
+ DEFAULT_SIDECAR_TAG = :div
8
+ DEFAULT_ASIDE_TAG = :div
9
+ DEFAULT_MAIN_TAG = :div
10
+
11
+ DEFAULT_CLASSES = {
12
+ wrapper: "ariadne-group ariadne-flex ariadne-gap-2 ariadne-flex-col md:ariadne-flex-row",
13
+ sidecar: "ariadne-w-full md:ariadne-w-1/6",
14
+ main: "ariadne-grow",
15
+ aside: "ariadne-w-full md:ariadne-w-1/6",
16
+ }
17
+
18
+ DEFAULT_ATTRIBUTES = {
19
+ wrapper: {},
20
+ sidecar: {},
21
+ main: {},
22
+ aside: {},
23
+ }
24
+
25
+ renders_many :sidecars
26
+
27
+ renders_many :mains
28
+
29
+ renders_many :asides
30
+
31
+ # @example Default
32
+ #
33
+ # <%= render(Ariadne::LayoutComponent.new) { "Example" } %>
34
+ #
35
+ # @param tag [Symbol, String] The rendered tag name.
36
+ # @param classes [String] <%= link_to_classes_docs %>
37
+ # @param attributes [Hash] <%= link_to_attributes_docs %>
38
+ def initialize(
39
+ tag: DEFAULT_TAG,
40
+ classes: "",
41
+ attributes: {},
42
+ main_tag: DEFAULT_MAIN_TAG,
43
+ main_classes: "",
44
+ main_attributes: {},
45
+ sidecar_tag: DEFAULT_SIDECAR_TAG,
46
+ sidecar_classes: "",
47
+ sidecar_attributes: {},
48
+ aside_tag: DEFAULT_ASIDE_TAG,
49
+ aside_classes: "",
50
+ aside_attributes: {}
51
+ )
52
+ @tag = check_incoming_tag(DEFAULT_TAG, tag)
53
+ @classes = merge_class_names(DEFAULT_CLASSES[:wrapper], classes)
54
+ @attributes = DEFAULT_ATTRIBUTES[:wrapper].merge(attributes)
55
+
56
+ @sidecar_tag = check_incoming_tag(DEFAULT_SIDECAR_TAG, tag)
57
+ @sidecar_attributes = DEFAULT_ATTRIBUTES[:sidecar].merge(sidecar_attributes)
58
+ @sidecar_classes = merge_class_names(DEFAULT_CLASSES[:sidecar], sidecar_classes)
59
+
60
+ @main_tag = check_incoming_tag(DEFAULT_MAIN_TAG, tag)
61
+ @main_attributes = DEFAULT_ATTRIBUTES[:main].merge(main_attributes)
62
+ @main_classes = merge_class_names(DEFAULT_CLASSES[:main], main_classes)
63
+
64
+ @aside_tag = check_incoming_tag(DEFAULT_ASIDE_TAG, tag)
65
+ @aside_attributes = DEFAULT_ATTRIBUTES[:aside].merge(aside_attributes)
66
+ @aside_classes = merge_class_names(DEFAULT_CLASSES[:aside], aside_classes)
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,11 @@
1
+ <%= render Ariadne::BaseComponent.new(tag: @tag, classes: @classes, attributes: @attributes) do %>
2
+ <%= base %>
3
+ <%= render Ariadne::BaseComponent.new(tag: @shadow_tag, classes: @shadow_classes, attributes: @shadow_attributes) do %>
4
+ <div class="<%= @content_classes %>" data-controller="events" data-action="click->events#stopPropagation">
5
+ <%= render Ariadne::CloseButtonComponent.new(classes: @close_button_classes, aria_label: @close_button_aria_label, attributes: { "data-action": "click->toggleable#toggle" }) %>
6
+ <% items.each do |item| %>
7
+ <%= item %>
8
+ <% end %>
9
+ </div>
10
+ <% end %>
11
+ <% end %>
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ariadne
4
+ # Renders a full screen modal
5
+ class ModalComponent < Ariadne::Component
6
+ DEFAULT_TAG = :div
7
+ DEFAULT_SHADOW_TAG = :div
8
+ TAG_OPTIONS = [DEFAULT_TAG].freeze
9
+
10
+ DEFAULT_CLASSES = {
11
+ wrapper: "ariadne-group",
12
+ shadow: "ariadne-w-screen ariadne-h-screen ariadne-bg-black/20 ariadne-fixed ariadne-top-0 ariadne-left-0 ariadne-flex ariadne-justify-center ariadne-items-center data-[close-on-click=true]:ariadne-cursor-pointer",
13
+ content: "ariadne-bg-white ariadne-p-2 ariadne-relative ariadne-cursor-default",
14
+ close_button: "ariadne-absolute ariadne-right-2 ariadne-pt-1 ariadne-pb-1 ariadne-pl-1 ariadne-pr-1",
15
+ }
16
+
17
+ DEFAULT_ATTRIBUTES = {
18
+ wrapper: {
19
+ "data-controller": "toggleable",
20
+ "data-action": "click->toggleable#toggle",
21
+ "data-toggleable-anti-attrs-value": '["aria-hidden"]',
22
+ },
23
+ shadow: {},
24
+ content: { role: :dialog },
25
+ close_button: {},
26
+ }
27
+
28
+ SHADOW_VISIBILITY_CLASSES = "group-aria-hidden:ariadne-hidden"
29
+
30
+ renders_one :base
31
+
32
+ renders_many :items
33
+
34
+ # @example Default
35
+ #
36
+ # <%= render(Ariadne::ModalComponent.new) { "Example" } %>
37
+ #
38
+ # @param tag [Symbol, String] The rendered tag name.
39
+ # @param classes [String] <%= link_to_classes_docs %>
40
+ # @param attributes [Hash] <%= link_to_attributes_docs %>
41
+ def initialize(
42
+ tag: DEFAULT_TAG,
43
+ classes: "",
44
+ attributes: {},
45
+ initial_visible: false,
46
+ shadow_tag: DEFAULT_SHADOW_TAG,
47
+ shadow_classes: "",
48
+ shadow_attributes: {},
49
+ content_classes: "",
50
+ content_attributes: {},
51
+ close_button_classes: "",
52
+ close_button_attributes: {},
53
+ close_button_aria_label: "Close modal button",
54
+ close_on_shadow_click: true
55
+ )
56
+ @tag = check_incoming_tag(DEFAULT_TAG, tag)
57
+ @classes = merge_class_names(DEFAULT_CLASSES[:wrapper], classes)
58
+ @attributes = DEFAULT_ATTRIBUTES[:wrapper]
59
+ .merge({
60
+ "aria-hidden": true,
61
+ "data-toggleable-state-value": false,
62
+ })
63
+ .merge(attributes)
64
+
65
+ @initial_visible = initial_visible
66
+ @shadow_tag = check_incoming_tag(DEFAULT_SHADOW_TAG, shadow_tag)
67
+ @shadow_classes = merge_class_names(
68
+ DEFAULT_CLASSES[:shadow],
69
+ SHADOW_VISIBILITY_CLASSES,
70
+ shadow_classes,
71
+ )
72
+ @shadow_attributes = DEFAULT_ATTRIBUTES[:shadow]
73
+ .merge({
74
+ "data-controller": "events",
75
+ "data-close-on-click": close_on_shadow_click,
76
+ "data-action": close_on_shadow_click ? "" : "click->events#stopPropagation",
77
+ })
78
+ .merge(shadow_attributes)
79
+
80
+ @content_classes = merge_class_names(DEFAULT_CLASSES[:content], content_classes)
81
+ @content_attributes = DEFAULT_ATTRIBUTES[:content].merge(content_attributes)
82
+
83
+ @close_button_aria_label = close_button_aria_label
84
+ @close_button_classes = merge_class_names(DEFAULT_CLASSES[:close_button], close_button_classes)
85
+ @close_button_attributes = DEFAULT_ATTRIBUTES[:content].merge(content_attributes)
86
+ end
87
+ end
88
+ end
@@ -1,21 +1,40 @@
1
- import { Controller } from '@hotwired/stimulus';
2
- export default class OptionsController extends Controller {
1
+ import { TOutletChangeData } from '../outlet_manager_controller/outlet_manager_controller';
2
+ import SyncedBooleanAttributesController from '../synced_boolean_attributes_controller/synced_boolean_attributes_controller';
3
+ type TOptionKey = string | number;
4
+ type TActiveOptions = {
5
+ [k: TOptionKey]: boolean;
6
+ };
7
+ export interface OptionsOutlet extends SyncedBooleanAttributesController<TActiveOptions> {
8
+ select: (e: Event, updateTo?: TOutletChangeData<TActiveOptions>) => void;
9
+ }
10
+ export default class OptionsController extends SyncedBooleanAttributesController<TActiveOptions> implements OptionsOutlet {
3
11
  #private;
12
+ static outlets: string[];
4
13
  static targets: string[];
5
14
  static values: {
6
- activeIndex: {
7
- type: NumberConstructor;
8
- default: number;
15
+ activeOptions: ObjectConstructor;
16
+ isMulti: {
17
+ type: BooleanConstructor;
18
+ default: boolean;
19
+ };
20
+ toggleable: {
21
+ type: BooleanConstructor;
22
+ default: boolean;
9
23
  };
10
24
  syncedAttrs: ArrayConstructor;
11
25
  antiAttrs: ArrayConstructor;
26
+ protectAttrs: BooleanConstructor;
27
+ outletEvents: ArrayConstructor;
12
28
  };
13
29
  readonly optionTargets: Array<Element>;
14
- activeIndexValue: number;
15
- readonly syncedAttrsValue: string[];
16
- readonly hasSyncedAttrsValue: boolean;
17
- readonly antiAttrsValue: string[];
18
- readonly hasAntiAttrsValue: boolean;
30
+ activeOptionsValue: TActiveOptions;
31
+ readonly isMultiValue: boolean;
32
+ readonly toggleableValue: boolean;
33
+ optionTargetLookup: Map<Element, TOptionKey>;
19
34
  connect(): void;
20
- select(e: Event, newIndex?: number): void;
35
+ select(event: Event, updateTo?: TOutletChangeData<TActiveOptions>): void;
36
+ getValueForElement(element: Element): boolean | null;
37
+ getState(): TActiveOptions;
38
+ outletUpdate: (event: Event, updateTo?: TOutletChangeData<TActiveOptions>) => void;
21
39
  }
40
+ export {};