ariadne_view_components 0.0.59 → 0.0.64
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +68 -0
- data/LICENSE.txt +661 -49
- data/README.md +52 -4
- data/app/assets/javascripts/ariadne_view_components.js +98 -7
- data/app/assets/javascripts/ariadne_view_components.js.map +1 -1
- data/app/assets/stylesheets/ariadne_view_components.css +1 -7
- data/app/components/ariadne/base_component.rb +79 -27
- data/app/components/ariadne/behaviors/tooltipable.rb +120 -0
- data/app/components/ariadne/conditional_wrapper.rb +21 -0
- data/app/components/ariadne/form/base_component.rb +74 -0
- data/app/components/ariadne/form/base_input_component.rb +60 -0
- data/app/components/ariadne/form/caption/component.html.erb +10 -0
- data/app/components/ariadne/form/caption/component.rb +29 -0
- data/app/components/ariadne/form/form_control/component.html.erb +19 -0
- data/app/components/ariadne/form/form_control/component.rb +27 -0
- data/app/components/ariadne/form/form_reference/component.html.erb +1 -0
- data/app/components/ariadne/form/form_reference/component.rb +18 -0
- data/app/components/ariadne/form/group/component.html.erb +5 -0
- data/app/components/ariadne/form/group/component.rb +27 -0
- data/app/components/ariadne/form/hidden_field/component.html.erb +1 -0
- data/app/components/ariadne/form/hidden_field/component.rb +15 -0
- data/app/components/ariadne/form/separator/component.html.erb +1 -0
- data/app/components/ariadne/form/separator/component.rb +8 -0
- data/app/components/ariadne/form/spacing_wrapper/component.html.erb +3 -0
- data/app/components/ariadne/form/spacing_wrapper/component.rb +8 -0
- data/app/components/ariadne/form/text_field/component.html.erb +25 -0
- data/app/components/ariadne/form/text_field/component.rb +132 -0
- data/app/components/ariadne/form/validation_message/component.html.erb +5 -0
- data/app/components/ariadne/form/validation_message/component.rb +14 -0
- data/app/components/ariadne/layout/narrow/component.html.erb +10 -0
- data/app/components/ariadne/layout/narrow/component.rb +24 -0
- data/app/components/ariadne/layout/nav_bar/component.css +0 -0
- data/app/components/ariadne/layout/nav_bar/component.html.erb +123 -0
- data/app/components/ariadne/layout/nav_bar/component.rb +77 -0
- data/app/components/ariadne/ui/button/component.html.erb +5 -0
- data/app/components/ariadne/ui/button/component.rb +184 -0
- data/app/components/ariadne/ui/clipboard_copy/component.html.erb +8 -0
- data/app/components/ariadne/ui/clipboard_copy/component.rb +102 -0
- data/app/components/ariadne/ui/clipboard_copy/component.ts +54 -0
- data/app/components/ariadne/ui/combobox/component.html.erb +32 -0
- data/app/components/ariadne/ui/combobox/component.rb +83 -0
- data/app/components/ariadne/ui/combobox/component.ts +119 -0
- data/app/components/ariadne/ui/combobox/menu_item/component.html.erb +9 -0
- data/app/components/ariadne/ui/combobox/menu_item/component.rb +53 -0
- data/app/components/ariadne/ui/combobox/option/component.html.erb +11 -0
- data/app/components/ariadne/ui/combobox/option/component.rb +45 -0
- data/app/components/ariadne/ui/heroicon/component.html.erb +3 -0
- data/app/components/ariadne/ui/heroicon/component.rb +141 -0
- data/app/components/ariadne/ui/image/component.rb +69 -0
- data/app/components/ariadne/ui/link/component.html.erb +3 -0
- data/app/components/ariadne/ui/link/component.rb +56 -0
- data/app/components/ariadne/ui/typography/component.html.erb +3 -0
- data/app/components/ariadne/ui/typography/component.rb +41 -0
- data/app/lib/ariadne/attributes_helper.rb +119 -0
- data/app/lib/ariadne/fetch_or_fallback_helper.rb +1 -1
- data/app/lib/ariadne/form.rb +16 -0
- data/app/lib/ariadne/view_helper.rb +2 -5
- data/app/lib/view_components_contrib/html_attrs.rb +64 -0
- data/app/lib/view_components_contrib/style_variants.rb +14 -0
- data/lib/ariadne/forms/acts_as_component.rb +125 -0
- data/lib/ariadne/forms/base.html.erb +8 -0
- data/lib/ariadne/forms/base.rb +132 -0
- data/lib/ariadne/forms/buffer_rewriter.rb +51 -0
- data/lib/ariadne/forms/builder.rb +88 -0
- data/lib/ariadne/forms/dsl/button_input.rb +33 -0
- data/lib/ariadne/forms/dsl/form_object.rb +26 -0
- data/lib/ariadne/forms/dsl/input.rb +322 -0
- data/lib/ariadne/forms/dsl/input_group.rb +34 -0
- data/lib/ariadne/forms/dsl/input_methods.rb +157 -0
- data/lib/ariadne/forms/dsl/submit_button_input.rb +36 -0
- data/lib/ariadne/forms/dsl/text_field_input.rb +73 -0
- data/lib/ariadne/forms/utils.rb +34 -0
- data/lib/ariadne/generate.rb +11 -0
- data/lib/ariadne/view_components/engine.rb +24 -7
- data/lib/ariadne/view_components/version.rb +1 -1
- data/lib/ariadne/view_components.rb +1 -1
- data/lib/ariadne/yard/backend.rb +24 -0
- data/lib/ariadne/yard/component_manifest.rb +148 -0
- data/lib/ariadne/yard/component_ref.rb +49 -0
- data/lib/ariadne/yard/docs_helper.rb +98 -0
- data/lib/ariadne/yard/info_arch_docs_helper.rb +31 -0
- data/lib/ariadne/yard/lookbook_docs_helper.rb +32 -0
- data/lib/ariadne/yard/lookbook_pages_backend.rb +235 -0
- data/lib/ariadne/yard/registry.rb +136 -0
- data/lib/ariadne/yard/renders_many_handler.rb +23 -0
- data/lib/ariadne/yard/renders_one_handler.rb +23 -0
- data/lib/ariadne/yard.rb +19 -0
- data/static/arguments.yml +141 -48
- data/static/audited_at.json +0 -9
- data/static/classes.yml +210 -209
- data/static/constants.json +2 -209
- data/static/statuses.json +0 -9
- metadata +125 -210
- data/app/assets/builds/ariadne_view_components.css +0 -2202
- data/app/assets/javascripts/components/ariadne/accumulator_controller/accumulator_controller.d.ts +0 -22
- data/app/assets/javascripts/components/ariadne/ariadne-form.d.ts +0 -22
- data/app/assets/javascripts/components/ariadne/ariadne.d.ts +0 -2
- data/app/assets/javascripts/components/ariadne/clipboard_copy_component/clipboard-copy-component.d.ts +0 -4
- data/app/assets/javascripts/components/ariadne/dropdown/menu_component.d.ts +0 -1
- data/app/assets/javascripts/components/ariadne/events_controller/events_controller.d.ts +0 -4
- data/app/assets/javascripts/components/ariadne/options_controller/options_controller.d.ts +0 -39
- data/app/assets/javascripts/components/ariadne/outlet_manager_controller/outlet_manager_controller.d.ts +0 -42
- data/app/assets/javascripts/components/ariadne/slideover_component/slideover-component.d.ts +0 -9
- data/app/assets/javascripts/components/ariadne/string_match_controller/string_match_controller.d.ts +0 -27
- data/app/assets/javascripts/components/ariadne/synced_boolean_attributes_controller/synced_boolean_attributes_controller.d.ts +0 -48
- data/app/assets/javascripts/components/ariadne/tab_container_component/tab-container-component.d.ts +0 -1
- data/app/assets/javascripts/components/ariadne/tab_nav_component/tab-nav-component.d.ts +0 -9
- data/app/assets/javascripts/components/ariadne/time_ago_component/time-ago-component.d.ts +0 -1
- data/app/assets/javascripts/components/ariadne/toggleable_controller/toggleable_controller.d.ts +0 -34
- data/app/assets/javascripts/components/ariadne/tooltip_component/tooltip-component.d.ts +0 -24
- data/app/assets/stylesheets/dropdown.css +0 -46
- data/app/assets/stylesheets/prosemirror.css +0 -323
- data/app/assets/stylesheets/tooltip-component.css +0 -37
- data/app/components/ariadne/accumulator_controller/accumulator_controller.d.ts +0 -22
- data/app/components/ariadne/accumulator_controller/accumulator_controller.js +0 -39
- data/app/components/ariadne/accumulator_controller/accumulator_controller.ts +0 -48
- data/app/components/ariadne/action_card_component.html.erb +0 -13
- data/app/components/ariadne/action_card_component.rb +0 -88
- data/app/components/ariadne/ariadne-form.d.ts +0 -22
- data/app/components/ariadne/ariadne-form.js +0 -85
- data/app/components/ariadne/ariadne.d.ts +0 -2
- data/app/components/ariadne/ariadne.js +0 -24
- data/app/components/ariadne/ariadne.ts +0 -29
- data/app/components/ariadne/avatar_component.rb +0 -81
- data/app/components/ariadne/avatar_stack_component/avatar_stack_component.html.erb +0 -12
- data/app/components/ariadne/avatar_stack_component.rb +0 -75
- data/app/components/ariadne/base_button.rb +0 -70
- data/app/components/ariadne/blankslate_component/blankslate_component.html.erb +0 -26
- data/app/components/ariadne/blankslate_component.rb +0 -148
- data/app/components/ariadne/body_component.rb +0 -30
- data/app/components/ariadne/bottom_tab_component.html.erb +0 -4
- data/app/components/ariadne/bottom_tab_component.rb +0 -44
- data/app/components/ariadne/bottom_tab_nav_component.html.erb +0 -5
- data/app/components/ariadne/bottom_tab_nav_component.rb +0 -33
- data/app/components/ariadne/breadcrumbs_component.html.erb +0 -13
- data/app/components/ariadne/breadcrumbs_component.rb +0 -31
- data/app/components/ariadne/button_component/button_component.html.erb +0 -4
- data/app/components/ariadne/button_component.rb +0 -165
- data/app/components/ariadne/checkbox_component.html.erb +0 -5
- data/app/components/ariadne/checkbox_component.rb +0 -43
- data/app/components/ariadne/clipboard_copy_component/clipboard-copy-component.d.ts +0 -4
- data/app/components/ariadne/clipboard_copy_component/clipboard-copy-component.js +0 -18
- data/app/components/ariadne/clipboard_copy_component/clipboard-copy-component.ts +0 -19
- data/app/components/ariadne/clipboard_copy_component/clipboard_copy_component.html.erb +0 -9
- data/app/components/ariadne/clipboard_copy_component.rb +0 -90
- data/app/components/ariadne/close_button_component.html.erb +0 -4
- data/app/components/ariadne/close_button_component.rb +0 -33
- data/app/components/ariadne/combobox_component.html.erb +0 -14
- data/app/components/ariadne/combobox_component.rb +0 -76
- data/app/components/ariadne/component.rb +0 -127
- data/app/components/ariadne/container_component/container_component.html.erb +0 -3
- data/app/components/ariadne/container_component.rb +0 -25
- data/app/components/ariadne/content.rb +0 -12
- data/app/components/ariadne/counter_component.rb +0 -100
- data/app/components/ariadne/details_component/details_component.html.erb +0 -4
- data/app/components/ariadne/details_component.rb +0 -81
- data/app/components/ariadne/dropdown/menu_component.d.ts +0 -1
- data/app/components/ariadne/dropdown/menu_component.html.erb +0 -20
- data/app/components/ariadne/dropdown/menu_component.js +0 -1
- data/app/components/ariadne/dropdown/menu_component.rb +0 -101
- data/app/components/ariadne/dropdown/menu_component.ts +0 -1
- data/app/components/ariadne/dropdown_component/dropdown_component.html.erb +0 -8
- data/app/components/ariadne/dropdown_component.rb +0 -172
- data/app/components/ariadne/events_controller/events_controller.d.ts +0 -4
- data/app/components/ariadne/events_controller/events_controller.js +0 -6
- data/app/components/ariadne/events_controller/events_controller.ts +0 -7
- data/app/components/ariadne/flash_component/flash_component.html.erb +0 -31
- data/app/components/ariadne/flash_component.rb +0 -128
- data/app/components/ariadne/flex_component/flex_component.html.erb +0 -5
- data/app/components/ariadne/flex_component.rb +0 -56
- data/app/components/ariadne/footer_component/footer_component.html.erb +0 -7
- data/app/components/ariadne/footer_component.rb +0 -23
- data/app/components/ariadne/grid_component/grid_component.html.erb +0 -26
- data/app/components/ariadne/grid_component.rb +0 -67
- data/app/components/ariadne/header_component/header_component.html.erb +0 -29
- data/app/components/ariadne/header_component.rb +0 -111
- data/app/components/ariadne/heading_component.rb +0 -49
- data/app/components/ariadne/heroicon_component/heroicon_component.html.erb +0 -4
- data/app/components/ariadne/heroicon_component.rb +0 -166
- data/app/components/ariadne/image_component.rb +0 -53
- data/app/components/ariadne/inline_flex_component/inline_flex_component.html.erb +0 -6
- data/app/components/ariadne/inline_flex_component.rb +0 -72
- data/app/components/ariadne/layout_component.html.erb +0 -21
- data/app/components/ariadne/layout_component.rb +0 -69
- data/app/components/ariadne/link_component.rb +0 -65
- data/app/components/ariadne/list_component/list_component.html.erb +0 -3
- data/app/components/ariadne/list_component.rb +0 -70
- data/app/components/ariadne/modal_component.html.erb +0 -11
- data/app/components/ariadne/modal_component.rb +0 -88
- data/app/components/ariadne/narrow_container_component/narrow_container_component.html.erb +0 -3
- data/app/components/ariadne/narrow_container_component.rb +0 -30
- data/app/components/ariadne/options_controller/options_controller.d.ts +0 -39
- data/app/components/ariadne/options_controller/options_controller.js +0 -89
- data/app/components/ariadne/options_controller/options_controller.ts +0 -122
- data/app/components/ariadne/outlet_manager_controller/outlet_manager_controller.d.ts +0 -42
- data/app/components/ariadne/outlet_manager_controller/outlet_manager_controller.js +0 -237
- data/app/components/ariadne/outlet_manager_controller/outlet_manager_controller.ts +0 -278
- data/app/components/ariadne/panel_bar_component/panel_bar_component.html.erb +0 -20
- data/app/components/ariadne/panel_bar_component.rb +0 -80
- data/app/components/ariadne/pill_component/pill_component.html.erb +0 -3
- data/app/components/ariadne/pill_component.rb +0 -44
- data/app/components/ariadne/popover_component.html.erb +0 -10
- data/app/components/ariadne/popover_component.rb +0 -81
- data/app/components/ariadne/progress_bar_component.html.erb +0 -5
- data/app/components/ariadne/progress_bar_component.rb +0 -63
- data/app/components/ariadne/relative_time_component.html.erb +0 -3
- data/app/components/ariadne/relative_time_component.rb +0 -61
- data/app/components/ariadne/show_more_button_component.html.erb +0 -11
- data/app/components/ariadne/show_more_button_component.rb +0 -47
- data/app/components/ariadne/slideover_component/slideover-component.d.ts +0 -9
- data/app/components/ariadne/slideover_component/slideover-component.js +0 -11
- data/app/components/ariadne/slideover_component/slideover-component.ts +0 -17
- data/app/components/ariadne/slideover_component/slideover_component.html.erb +0 -9
- data/app/components/ariadne/slideover_component.rb +0 -66
- data/app/components/ariadne/spinner_component.html.erb +0 -16
- data/app/components/ariadne/spinner_component.rb +0 -45
- data/app/components/ariadne/string_match_controller/string_match_controller.d.ts +0 -27
- data/app/components/ariadne/string_match_controller/string_match_controller.js +0 -51
- data/app/components/ariadne/string_match_controller/string_match_controller.ts +0 -65
- data/app/components/ariadne/subheader_component.html.erb +0 -11
- data/app/components/ariadne/subheader_component.rb +0 -65
- data/app/components/ariadne/synced_boolean_attributes_controller/synced_boolean_attributes_controller.d.ts +0 -48
- data/app/components/ariadne/synced_boolean_attributes_controller/synced_boolean_attributes_controller.js +0 -207
- data/app/components/ariadne/synced_boolean_attributes_controller/synced_boolean_attributes_controller.ts +0 -256
- data/app/components/ariadne/tab_component/tab_component.html.erb +0 -3
- data/app/components/ariadne/tab_component.rb +0 -98
- data/app/components/ariadne/tab_container_component/tab-container-component.d.ts +0 -1
- data/app/components/ariadne/tab_container_component/tab-container-component.js +0 -23
- data/app/components/ariadne/tab_container_component/tab-container-component.ts +0 -24
- data/app/components/ariadne/tab_container_component.erb +0 -10
- data/app/components/ariadne/tab_container_component.rb +0 -68
- data/app/components/ariadne/tab_nav_component/tab-nav-component.d.ts +0 -9
- data/app/components/ariadne/tab_nav_component/tab-nav-component.js +0 -33
- data/app/components/ariadne/tab_nav_component/tab-nav-component.ts +0 -34
- data/app/components/ariadne/tab_nav_component/tab_nav_component.html.erb +0 -7
- data/app/components/ariadne/tab_nav_component.rb +0 -72
- data/app/components/ariadne/table_nav_component/table_nav_component.html.erb +0 -52
- data/app/components/ariadne/table_nav_component.rb +0 -338
- data/app/components/ariadne/text.rb +0 -25
- data/app/components/ariadne/time_ago_component/time-ago-component.d.ts +0 -1
- data/app/components/ariadne/time_ago_component/time-ago-component.js +0 -1
- data/app/components/ariadne/time_ago_component/time-ago-component.ts +0 -1
- data/app/components/ariadne/time_ago_component.rb +0 -56
- data/app/components/ariadne/timeline_component/timeline_component.html.erb +0 -19
- data/app/components/ariadne/timeline_component.rb +0 -34
- data/app/components/ariadne/toggle_component/toggle_component.html.erb +0 -15
- data/app/components/ariadne/toggle_component.rb +0 -95
- data/app/components/ariadne/toggleable_controller/toggleable_controller.d.ts +0 -34
- data/app/components/ariadne/toggleable_controller/toggleable_controller.js +0 -54
- data/app/components/ariadne/toggleable_controller/toggleable_controller.ts +0 -77
- data/app/components/ariadne/tooltip_component/tooltip-component.d.ts +0 -24
- data/app/components/ariadne/tooltip_component/tooltip-component.js +0 -43
- data/app/components/ariadne/tooltip_component/tooltip-component.ts +0 -57
- data/app/components/ariadne/tooltip_component/tooltip_component.html.erb +0 -4
- data/app/components/ariadne/tooltip_component.rb +0 -108
- data/app/lib/ariadne/action_view_extensions/form_helper.rb +0 -30
- data/app/lib/ariadne/audited/dsl.rb +0 -32
- data/app/lib/ariadne/form_builder.rb +0 -80
- data/app/lib/ariadne/status/dsl.rb +0 -41
- data/config/importmap.rb +0 -3
- data/exe/tailwindcss +0 -21
- data/lib/rubocop/cop/ariadne/base_cop.rb +0 -26
- data/tailwind.config.js +0 -70
@@ -1,65 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Ariadne
|
4
|
-
# A component to render a subheader with optional description below it and optional action
|
5
|
-
# components on the right side
|
6
|
-
class SubheaderComponent < Ariadne::Component
|
7
|
-
DEFAULT_TAGS = {
|
8
|
-
wrapper: :div,
|
9
|
-
actions: :div,
|
10
|
-
header: :h2,
|
11
|
-
description: :span,
|
12
|
-
}
|
13
|
-
|
14
|
-
DEFAULT_CLASSES = {
|
15
|
-
wrapper: "ariadne-border-b-2 ariadne-border-solid ariadne-border-black ariadne-border-opacity-20",
|
16
|
-
header: "",
|
17
|
-
actions: "",
|
18
|
-
description: "ariadne-text-black/50",
|
19
|
-
}
|
20
|
-
|
21
|
-
DEFAULT_ATTRIBUTES = {
|
22
|
-
wrapper: {},
|
23
|
-
header: {},
|
24
|
-
description: {},
|
25
|
-
actions: {},
|
26
|
-
}
|
27
|
-
|
28
|
-
renders_one :header, lambda { |tag: DEFAULT_TAGS[:header], classes: "", attributes: {}|
|
29
|
-
Ariadne::HeadingComponent.new(
|
30
|
-
tag: check_incoming_tag(DEFAULT_TAGS[:header], tag),
|
31
|
-
classes: merge_class_names(DEFAULT_CLASSES[:header], classes),
|
32
|
-
attributes: DEFAULT_ATTRIBUTES[:header].merge({ id: @header_id }).merge(attributes),
|
33
|
-
)
|
34
|
-
}
|
35
|
-
|
36
|
-
renders_one :description, lambda { |tag: DEFAULT_TAGS[:description], classes: "", attributes: {}|
|
37
|
-
Ariadne::BaseComponent.new(
|
38
|
-
tag: check_incoming_tag(DEFAULT_TAGS[:description], tag),
|
39
|
-
classes: merge_class_names(DEFAULT_CLASSES[:description], classes),
|
40
|
-
attributes: DEFAULT_ATTRIBUTES[:description]
|
41
|
-
.merge({ "aria-describedby": @header_id })
|
42
|
-
.merge(attributes),
|
43
|
-
)
|
44
|
-
}
|
45
|
-
|
46
|
-
renders_many :actions
|
47
|
-
|
48
|
-
# @example Default
|
49
|
-
#
|
50
|
-
# <%= render(Ariadne::SubheaderComponent.new) { "Example" } %>
|
51
|
-
#
|
52
|
-
# @param tag [Symbol, String] The rendered tag name.
|
53
|
-
# @param classes [String] <%= link_to_classes_docs %>
|
54
|
-
# @param attributes [Hash] <%= link_to_attributes_docs %>
|
55
|
-
def initialize(tag: DEFAULT_TAGS[:wrapper], classes: "", id: "subheader-#{SecureRandom.uuid}", attributes: {})
|
56
|
-
@tag = check_incoming_tag(DEFAULT_TAGS[:wrapper], tag)
|
57
|
-
@header_id = id
|
58
|
-
@attributes = DEFAULT_ATTRIBUTES[:wrapper].merge(attributes)
|
59
|
-
@classes = merge_class_names(
|
60
|
-
DEFAULT_CLASSES[:wrapper],
|
61
|
-
classes,
|
62
|
-
)
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
@@ -1,48 +0,0 @@
|
|
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
|
-
getSyncedAttrsForElement(element: Element): string[] | null;
|
43
|
-
getAntiAttrsForElement(element: Element): string[] | null;
|
44
|
-
getParsedAttributeForElement<T>(element: Element, attribute: string): T | null;
|
45
|
-
syncElementAttributes(): void;
|
46
|
-
validateAttrChange(dispatchEvent: TStimulusDispatchEvent<TSyncAttrDetail>): void;
|
47
|
-
doesElementHaveOnAttrs(element: Element): boolean;
|
48
|
-
}
|
@@ -1,207 +0,0 @@
|
|
1
|
-
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
2
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
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
|
-
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
5
|
-
};
|
6
|
-
var _SyncedBooleanAttributesController_instances, _SyncedBooleanAttributesController_isSyncedAttr, _SyncedBooleanAttributesController_isAntiAttr, _SyncedBooleanAttributesController_isAttr, _SyncedBooleanAttributesController_setAttrs, _SyncedBooleanAttributesController_getLookupForStringArray;
|
7
|
-
import OutletManagerController from '../outlet_manager_controller/outlet_manager_controller';
|
8
|
-
/*
|
9
|
-
This class isn't used directly by itself because it has no functionality. What it does is establishes
|
10
|
-
"synced attrs" and "anti-attrs" so that other controllers can extend this one and not worry about
|
11
|
-
implementing the logic themselves (and thus have duplicate logic all over our controllers)
|
12
|
-
|
13
|
-
To implement this, extend your controller with "SyncedBooleanAttributesController" then spread its
|
14
|
-
values into your controllers then implement:
|
15
|
-
|
16
|
-
export default class MyNewController extends SyncedBooleanAttributesController {
|
17
|
-
static values = {
|
18
|
-
...SyncedBooleanAttributesController.values,
|
19
|
-
myString: String,
|
20
|
-
}
|
21
|
-
}
|
22
|
-
|
23
|
-
Also, consider the functions defined here ABOVE the connection() function. Those functions will
|
24
|
-
give you control over how your controller can interact with other SyncedBooleanAttributeControllers.
|
25
|
-
Not every controller needs them but you should consider them (description can be found in the functions)
|
26
|
-
|
27
|
-
And don't forget that when you want to change an attr on an element, you should not do it manually.
|
28
|
-
Instead run:
|
29
|
-
this.updateAttributesForElement(element, value)
|
30
|
-
This will let you take advantage of the ecosystem created by this base controller without any additional work
|
31
|
-
*/
|
32
|
-
class SyncedBooleanAttributesController extends OutletManagerController {
|
33
|
-
constructor() {
|
34
|
-
super(...arguments);
|
35
|
-
_SyncedBooleanAttributesController_instances.add(this);
|
36
|
-
this.syncedAttrsLookup = null;
|
37
|
-
this.antiAttrsLookup = null;
|
38
|
-
}
|
39
|
-
getValueForElement(element) {
|
40
|
-
// This function allows the base controller to access a given element's
|
41
|
-
// current status so the attributes can be set or compared. For example,
|
42
|
-
// you will want to make sure the attributes are added initially and are
|
43
|
-
// in sync with the controller's state. To ensure this, you can use the
|
44
|
-
// default connect() function or add "this.syncElementAttributes()" to your
|
45
|
-
// custom connect function. It'll look through your targets and get values for
|
46
|
-
// each then set the appropriate attrs and anti-attrs
|
47
|
-
return null;
|
48
|
-
}
|
49
|
-
getElementsToSync() {
|
50
|
-
// These are the elements your controller wants to keep in sync with the attrs
|
51
|
-
// Sometimes these are this.element, sometimes they're specific targets.
|
52
|
-
// Return them here so the base controller can automate some behaviors for you
|
53
|
-
return [];
|
54
|
-
}
|
55
|
-
connect() {
|
56
|
-
// This function will sync attrs and anti-attrs when the controller connects.
|
57
|
-
// The logic is abstracted to a function so you can override this connect
|
58
|
-
// function in favor of your own without having to duplicate the sync logic
|
59
|
-
this.syncElementAttributes();
|
60
|
-
}
|
61
|
-
updateAttributesForElement(element, value) {
|
62
|
-
// This is how you should update any synced or anti-synced attrs on your elements
|
63
|
-
// Do not do it manually unless you are very sure of what you're doing
|
64
|
-
const syncedAttrs = this.getSyncedAttrsForElement(element);
|
65
|
-
if (syncedAttrs === null || syncedAttrs === void 0 ? void 0 : syncedAttrs.length) {
|
66
|
-
__classPrivateFieldGet(this, _SyncedBooleanAttributesController_instances, "m", _SyncedBooleanAttributesController_setAttrs).call(this, element, syncedAttrs, value);
|
67
|
-
}
|
68
|
-
const antiAttrs = this.getAntiAttrsForElement(element);
|
69
|
-
if (antiAttrs === null || antiAttrs === void 0 ? void 0 : antiAttrs.length) {
|
70
|
-
__classPrivateFieldGet(this, _SyncedBooleanAttributesController_instances, "m", _SyncedBooleanAttributesController_setAttrs).call(this, element, antiAttrs, !value);
|
71
|
-
}
|
72
|
-
}
|
73
|
-
getSyncedAttrsForElement(element) {
|
74
|
-
const parsedAttrs = this.getParsedAttributeForElement(element, 'data-options-synced-attrs-value');
|
75
|
-
if (parsedAttrs) {
|
76
|
-
return parsedAttrs;
|
77
|
-
}
|
78
|
-
if (this.hasSyncedAttrsValue) {
|
79
|
-
return this.syncedAttrsValue;
|
80
|
-
}
|
81
|
-
return null;
|
82
|
-
}
|
83
|
-
getAntiAttrsForElement(element) {
|
84
|
-
const parsedAttrs = this.getParsedAttributeForElement(element, 'data-options-anti-attrs-value');
|
85
|
-
if (parsedAttrs) {
|
86
|
-
return parsedAttrs;
|
87
|
-
}
|
88
|
-
if (this.hasAntiAttrsValue) {
|
89
|
-
return this.antiAttrsValue;
|
90
|
-
}
|
91
|
-
return null;
|
92
|
-
}
|
93
|
-
getParsedAttributeForElement(element, attribute) {
|
94
|
-
const attr = element.getAttribute(attribute);
|
95
|
-
try {
|
96
|
-
if (attr === null) {
|
97
|
-
throw new Error('Bad attr');
|
98
|
-
}
|
99
|
-
return JSON.parse(attr);
|
100
|
-
}
|
101
|
-
catch (err) {
|
102
|
-
return null;
|
103
|
-
}
|
104
|
-
}
|
105
|
-
syncElementAttributes() {
|
106
|
-
var _a;
|
107
|
-
this.syncOutlets();
|
108
|
-
// Essentially just a "sync attrs and anti-attrs on mount" function
|
109
|
-
const elements = this.getElementsToSync();
|
110
|
-
if (elements === null || elements === void 0 ? void 0 : elements.length) {
|
111
|
-
for (const index in elements) {
|
112
|
-
const element = elements[index];
|
113
|
-
const value = (_a = this.getValueForElement(element)) !== null && _a !== void 0 ? _a : false;
|
114
|
-
this.updateAttributesForElement(element, value);
|
115
|
-
}
|
116
|
-
}
|
117
|
-
}
|
118
|
-
validateAttrChange(dispatchEvent) {
|
119
|
-
// If you protect your attrs, then this function will deny other controllers you specify from making changes to them.
|
120
|
-
// For example, if you want an item to disappear when it's selected, then your Options controller likely has an "aria-hidden"
|
121
|
-
// synced attr. If you use another attr to filter the list and then remove that filter, normally that would unhide your selected
|
122
|
-
// element. But if you have Options protect its attrs, the filter behavior won't be allowed to change it at any time and thus
|
123
|
-
// the element will remain hidden
|
124
|
-
const { target, detail } = dispatchEvent;
|
125
|
-
if (target && detail) {
|
126
|
-
const currentValue = this.getValueForElement(target);
|
127
|
-
if (currentValue !== null && this.protectAttrsValue && __classPrivateFieldGet(this, _SyncedBooleanAttributesController_instances, "m", _SyncedBooleanAttributesController_isAttr).call(this, detail.attr)) {
|
128
|
-
dispatchEvent.preventDefault();
|
129
|
-
}
|
130
|
-
}
|
131
|
-
}
|
132
|
-
doesElementHaveOnAttrs(element) {
|
133
|
-
if (this.hasSyncedAttrsValue) {
|
134
|
-
for (let i = 0; i < this.syncedAttrsValue.length; i++) {
|
135
|
-
const attrName = this.syncedAttrsValue[i];
|
136
|
-
if (element.getAttribute(attrName) === 'true') {
|
137
|
-
return true;
|
138
|
-
}
|
139
|
-
}
|
140
|
-
}
|
141
|
-
if (this.hasAntiAttrsValue) {
|
142
|
-
for (let i = 0; i < this.antiAttrsValue.length; i++) {
|
143
|
-
const attrName = this.antiAttrsValue[i];
|
144
|
-
const attrValue = element.getAttribute(attrName);
|
145
|
-
if (attrValue === 'false' || (SyncedBooleanAttributesController.removeOnFalseAttrs[attrName] && !attrValue)) {
|
146
|
-
return true;
|
147
|
-
}
|
148
|
-
}
|
149
|
-
}
|
150
|
-
return false;
|
151
|
-
}
|
152
|
-
}
|
153
|
-
_SyncedBooleanAttributesController_instances = new WeakSet(), _SyncedBooleanAttributesController_isSyncedAttr = function _SyncedBooleanAttributesController_isSyncedAttr(attr) {
|
154
|
-
var _a;
|
155
|
-
// Helper function to determine if the attr is synced
|
156
|
-
if (this.syncedAttrsLookup === null) {
|
157
|
-
this.syncedAttrsLookup = __classPrivateFieldGet(this, _SyncedBooleanAttributesController_instances, "m", _SyncedBooleanAttributesController_getLookupForStringArray).call(this, this.syncedAttrsValue);
|
158
|
-
}
|
159
|
-
return (_a = this.syncedAttrsLookup[attr]) !== null && _a !== void 0 ? _a : false;
|
160
|
-
}, _SyncedBooleanAttributesController_isAntiAttr = function _SyncedBooleanAttributesController_isAntiAttr(attr) {
|
161
|
-
var _a;
|
162
|
-
// Helper function to determine if the attr is anti-synced
|
163
|
-
if (this.antiAttrsLookup === null) {
|
164
|
-
this.antiAttrsLookup = __classPrivateFieldGet(this, _SyncedBooleanAttributesController_instances, "m", _SyncedBooleanAttributesController_getLookupForStringArray).call(this, this.antiAttrsValue);
|
165
|
-
}
|
166
|
-
return (_a = this.antiAttrsLookup[attr]) !== null && _a !== void 0 ? _a : false;
|
167
|
-
}, _SyncedBooleanAttributesController_isAttr = function _SyncedBooleanAttributesController_isAttr(attr) {
|
168
|
-
// Helper function to determine if an attr is known to a controller
|
169
|
-
return __classPrivateFieldGet(this, _SyncedBooleanAttributesController_instances, "m", _SyncedBooleanAttributesController_isAntiAttr).call(this, attr) || __classPrivateFieldGet(this, _SyncedBooleanAttributesController_instances, "m", _SyncedBooleanAttributesController_isSyncedAttr).call(this, attr);
|
170
|
-
}, _SyncedBooleanAttributesController_setAttrs = function _SyncedBooleanAttributesController_setAttrs(element, attrs, value) {
|
171
|
-
// Attempts to change the attr for an element. However, it'll dispatch an event
|
172
|
-
// first so other controllers get the opportunity to deny it
|
173
|
-
const attrState = JSON.stringify(value);
|
174
|
-
for (const index in attrs) {
|
175
|
-
const attr = attrs[index];
|
176
|
-
const dispatchEvent = this.dispatch('attrChange', {
|
177
|
-
target: element,
|
178
|
-
detail: { attr, value },
|
179
|
-
});
|
180
|
-
if (!dispatchEvent.defaultPrevented) {
|
181
|
-
if (attrState === 'false' && SyncedBooleanAttributesController.removeOnFalseAttrs[attr]) {
|
182
|
-
element.removeAttribute(attr);
|
183
|
-
}
|
184
|
-
else {
|
185
|
-
element.setAttribute(attr, attrState);
|
186
|
-
}
|
187
|
-
}
|
188
|
-
}
|
189
|
-
}, _SyncedBooleanAttributesController_getLookupForStringArray = function _SyncedBooleanAttributesController_getLookupForStringArray(arr) {
|
190
|
-
// Helper function to return an array of strings into an object for easy lookup
|
191
|
-
// While the arrays contained here are small, looking up attrs will happen often
|
192
|
-
// so I think it's worth the small sacrifice to memory
|
193
|
-
if (!(arr === null || arr === void 0 ? void 0 : arr.length)) {
|
194
|
-
return {};
|
195
|
-
}
|
196
|
-
return arr.reduce((acc, cur) => {
|
197
|
-
acc[cur] = true;
|
198
|
-
return acc;
|
199
|
-
}, {});
|
200
|
-
};
|
201
|
-
SyncedBooleanAttributesController.values = Object.assign(Object.assign({}, OutletManagerController.values), { syncedAttrs: Array, antiAttrs: Array, protectAttrs: Boolean });
|
202
|
-
// Some attributes are only false in HTML if they don't exist
|
203
|
-
// If included here, the property will be deleted on "false"
|
204
|
-
SyncedBooleanAttributesController.removeOnFalseAttrs = {
|
205
|
-
checked: true,
|
206
|
-
};
|
207
|
-
export default SyncedBooleanAttributesController;
|
@@ -1,256 +0,0 @@
|
|
1
|
-
import OutletManagerController from '../outlet_manager_controller/outlet_manager_controller'
|
2
|
-
|
3
|
-
export type TStimulusDispatchEvent<TDetails> = {
|
4
|
-
target?: Element | undefined
|
5
|
-
detail?: TDetails | undefined
|
6
|
-
prefix?: string | undefined
|
7
|
-
bubbles?: boolean | undefined
|
8
|
-
cancelable?: boolean | undefined
|
9
|
-
preventDefault: () => void
|
10
|
-
}
|
11
|
-
|
12
|
-
export type TBooleanValueDetail = {
|
13
|
-
value: boolean
|
14
|
-
}
|
15
|
-
|
16
|
-
export interface TSyncAttrDetail extends TBooleanValueDetail {
|
17
|
-
attr: string
|
18
|
-
}
|
19
|
-
|
20
|
-
/*
|
21
|
-
This class isn't used directly by itself because it has no functionality. What it does is establishes
|
22
|
-
"synced attrs" and "anti-attrs" so that other controllers can extend this one and not worry about
|
23
|
-
implementing the logic themselves (and thus have duplicate logic all over our controllers)
|
24
|
-
|
25
|
-
To implement this, extend your controller with "SyncedBooleanAttributesController" then spread its
|
26
|
-
values into your controllers then implement:
|
27
|
-
|
28
|
-
export default class MyNewController extends SyncedBooleanAttributesController {
|
29
|
-
static values = {
|
30
|
-
...SyncedBooleanAttributesController.values,
|
31
|
-
myString: String,
|
32
|
-
}
|
33
|
-
}
|
34
|
-
|
35
|
-
Also, consider the functions defined here ABOVE the connection() function. Those functions will
|
36
|
-
give you control over how your controller can interact with other SyncedBooleanAttributeControllers.
|
37
|
-
Not every controller needs them but you should consider them (description can be found in the functions)
|
38
|
-
|
39
|
-
And don't forget that when you want to change an attr on an element, you should not do it manually.
|
40
|
-
Instead run:
|
41
|
-
this.updateAttributesForElement(element, value)
|
42
|
-
This will let you take advantage of the ecosystem created by this base controller without any additional work
|
43
|
-
*/
|
44
|
-
|
45
|
-
export default class SyncedBooleanAttributesController<T> extends OutletManagerController<T> {
|
46
|
-
static values = {
|
47
|
-
...OutletManagerController.values,
|
48
|
-
syncedAttrs: Array, // Set option target attrs to true/false in agreement with the option's selected state
|
49
|
-
antiAttrs: Array, // Set option target attrs to true/false opposite of the option's selected state
|
50
|
-
protectAttrs: Boolean, // If the controller should block other SyncedBooleanAttributesController from changing its defined attrs
|
51
|
-
}
|
52
|
-
|
53
|
-
declare readonly syncedAttrsValue: string[]
|
54
|
-
declare readonly hasSyncedAttrsValue: boolean
|
55
|
-
declare readonly antiAttrsValue: string[]
|
56
|
-
declare readonly hasAntiAttrsValue: boolean
|
57
|
-
declare readonly protectAttrsValue: boolean
|
58
|
-
|
59
|
-
// Some attributes are only false in HTML if they don't exist
|
60
|
-
// If included here, the property will be deleted on "false"
|
61
|
-
static removeOnFalseAttrs: {[k: string]: boolean} = {
|
62
|
-
checked: true,
|
63
|
-
}
|
64
|
-
|
65
|
-
syncedAttrsLookup: {[k: string]: boolean} | null = null
|
66
|
-
antiAttrsLookup: {[k: string]: boolean} | null = null
|
67
|
-
|
68
|
-
getValueForElement(element: Element): boolean | null {
|
69
|
-
// This function allows the base controller to access a given element's
|
70
|
-
// current status so the attributes can be set or compared. For example,
|
71
|
-
// you will want to make sure the attributes are added initially and are
|
72
|
-
// in sync with the controller's state. To ensure this, you can use the
|
73
|
-
// default connect() function or add "this.syncElementAttributes()" to your
|
74
|
-
// custom connect function. It'll look through your targets and get values for
|
75
|
-
// each then set the appropriate attrs and anti-attrs
|
76
|
-
return null
|
77
|
-
}
|
78
|
-
|
79
|
-
getElementsToSync(): Array<Element> | null | undefined {
|
80
|
-
// These are the elements your controller wants to keep in sync with the attrs
|
81
|
-
// Sometimes these are this.element, sometimes they're specific targets.
|
82
|
-
// Return them here so the base controller can automate some behaviors for you
|
83
|
-
return []
|
84
|
-
}
|
85
|
-
|
86
|
-
connect(): void {
|
87
|
-
// This function will sync attrs and anti-attrs when the controller connects.
|
88
|
-
// The logic is abstracted to a function so you can override this connect
|
89
|
-
// function in favor of your own without having to duplicate the sync logic
|
90
|
-
this.syncElementAttributes()
|
91
|
-
}
|
92
|
-
|
93
|
-
updateAttributesForElement(element: Element, value: boolean) {
|
94
|
-
// This is how you should update any synced or anti-synced attrs on your elements
|
95
|
-
// Do not do it manually unless you are very sure of what you're doing
|
96
|
-
const syncedAttrs = this.getSyncedAttrsForElement(element)
|
97
|
-
if (syncedAttrs?.length) {
|
98
|
-
this.#setAttrs(element, syncedAttrs, value)
|
99
|
-
}
|
100
|
-
|
101
|
-
const antiAttrs = this.getAntiAttrsForElement(element)
|
102
|
-
if (antiAttrs?.length) {
|
103
|
-
this.#setAttrs(element, antiAttrs, !value)
|
104
|
-
}
|
105
|
-
}
|
106
|
-
|
107
|
-
getSyncedAttrsForElement(element: Element) {
|
108
|
-
const parsedAttrs = this.getParsedAttributeForElement<Array<string>>(element, 'data-options-synced-attrs-value')
|
109
|
-
if (parsedAttrs) {
|
110
|
-
return parsedAttrs
|
111
|
-
}
|
112
|
-
|
113
|
-
if (this.hasSyncedAttrsValue) {
|
114
|
-
return this.syncedAttrsValue
|
115
|
-
}
|
116
|
-
|
117
|
-
return null
|
118
|
-
}
|
119
|
-
|
120
|
-
getAntiAttrsForElement(element: Element) {
|
121
|
-
const parsedAttrs = this.getParsedAttributeForElement<Array<string>>(element, 'data-options-anti-attrs-value')
|
122
|
-
if (parsedAttrs) {
|
123
|
-
return parsedAttrs
|
124
|
-
}
|
125
|
-
|
126
|
-
if (this.hasAntiAttrsValue) {
|
127
|
-
return this.antiAttrsValue
|
128
|
-
}
|
129
|
-
|
130
|
-
return null
|
131
|
-
}
|
132
|
-
|
133
|
-
getParsedAttributeForElement<T>(element: Element, attribute: string) {
|
134
|
-
const attr = element.getAttribute(attribute)
|
135
|
-
try {
|
136
|
-
if (attr === null) {
|
137
|
-
throw new Error('Bad attr')
|
138
|
-
}
|
139
|
-
|
140
|
-
return JSON.parse(attr) as T
|
141
|
-
} catch (err) {
|
142
|
-
return null
|
143
|
-
}
|
144
|
-
}
|
145
|
-
|
146
|
-
syncElementAttributes() {
|
147
|
-
this.syncOutlets()
|
148
|
-
// Essentially just a "sync attrs and anti-attrs on mount" function
|
149
|
-
const elements = this.getElementsToSync()
|
150
|
-
|
151
|
-
if (elements?.length) {
|
152
|
-
for (const index in elements) {
|
153
|
-
const element = elements[index]
|
154
|
-
const value = this.getValueForElement(element) ?? false
|
155
|
-
this.updateAttributesForElement(element, value)
|
156
|
-
}
|
157
|
-
}
|
158
|
-
}
|
159
|
-
|
160
|
-
validateAttrChange(dispatchEvent: TStimulusDispatchEvent<TSyncAttrDetail>) {
|
161
|
-
// If you protect your attrs, then this function will deny other controllers you specify from making changes to them.
|
162
|
-
// For example, if you want an item to disappear when it's selected, then your Options controller likely has an "aria-hidden"
|
163
|
-
// synced attr. If you use another attr to filter the list and then remove that filter, normally that would unhide your selected
|
164
|
-
// element. But if you have Options protect its attrs, the filter behavior won't be allowed to change it at any time and thus
|
165
|
-
// the element will remain hidden
|
166
|
-
const {target, detail} = dispatchEvent
|
167
|
-
if (target && detail) {
|
168
|
-
const currentValue = this.getValueForElement(target)
|
169
|
-
if (currentValue !== null && this.protectAttrsValue && this.#isAttr(detail.attr)) {
|
170
|
-
dispatchEvent.preventDefault()
|
171
|
-
}
|
172
|
-
}
|
173
|
-
}
|
174
|
-
|
175
|
-
doesElementHaveOnAttrs(element: Element) {
|
176
|
-
if (this.hasSyncedAttrsValue) {
|
177
|
-
for (let i = 0; i < this.syncedAttrsValue.length; i++) {
|
178
|
-
const attrName = this.syncedAttrsValue[i]
|
179
|
-
if (element.getAttribute(attrName) === 'true') {
|
180
|
-
return true
|
181
|
-
}
|
182
|
-
}
|
183
|
-
}
|
184
|
-
|
185
|
-
if (this.hasAntiAttrsValue) {
|
186
|
-
for (let i = 0; i < this.antiAttrsValue.length; i++) {
|
187
|
-
const attrName = this.antiAttrsValue[i]
|
188
|
-
const attrValue = element.getAttribute(attrName)
|
189
|
-
if (attrValue === 'false' || (SyncedBooleanAttributesController.removeOnFalseAttrs[attrName] && !attrValue)) {
|
190
|
-
return true
|
191
|
-
}
|
192
|
-
}
|
193
|
-
}
|
194
|
-
|
195
|
-
return false
|
196
|
-
}
|
197
|
-
|
198
|
-
#isSyncedAttr(attr: string) {
|
199
|
-
// Helper function to determine if the attr is synced
|
200
|
-
if (this.syncedAttrsLookup === null) {
|
201
|
-
this.syncedAttrsLookup = this.#getLookupForStringArray(this.syncedAttrsValue)
|
202
|
-
}
|
203
|
-
|
204
|
-
return this.syncedAttrsLookup[attr] ?? false
|
205
|
-
}
|
206
|
-
|
207
|
-
#isAntiAttr(attr: string) {
|
208
|
-
// Helper function to determine if the attr is anti-synced
|
209
|
-
if (this.antiAttrsLookup === null) {
|
210
|
-
this.antiAttrsLookup = this.#getLookupForStringArray(this.antiAttrsValue)
|
211
|
-
}
|
212
|
-
|
213
|
-
return this.antiAttrsLookup[attr] ?? false
|
214
|
-
}
|
215
|
-
|
216
|
-
#isAttr(attr: string) {
|
217
|
-
// Helper function to determine if an attr is known to a controller
|
218
|
-
return this.#isAntiAttr(attr) || this.#isSyncedAttr(attr)
|
219
|
-
}
|
220
|
-
|
221
|
-
#setAttrs(element: Element, attrs: string[], value: boolean) {
|
222
|
-
// Attempts to change the attr for an element. However, it'll dispatch an event
|
223
|
-
// first so other controllers get the opportunity to deny it
|
224
|
-
const attrState = JSON.stringify(value)
|
225
|
-
for (const index in attrs) {
|
226
|
-
const attr = attrs[index]
|
227
|
-
|
228
|
-
const dispatchEvent = this.dispatch('attrChange', {
|
229
|
-
target: element,
|
230
|
-
detail: {attr, value},
|
231
|
-
} as TStimulusDispatchEvent<TSyncAttrDetail>)
|
232
|
-
|
233
|
-
if (!dispatchEvent.defaultPrevented) {
|
234
|
-
if (attrState === 'false' && SyncedBooleanAttributesController.removeOnFalseAttrs[attr]) {
|
235
|
-
element.removeAttribute(attr)
|
236
|
-
} else {
|
237
|
-
element.setAttribute(attr, attrState)
|
238
|
-
}
|
239
|
-
}
|
240
|
-
}
|
241
|
-
}
|
242
|
-
|
243
|
-
#getLookupForStringArray(arr?: Array<string>) {
|
244
|
-
// Helper function to return an array of strings into an object for easy lookup
|
245
|
-
// While the arrays contained here are small, looking up attrs will happen often
|
246
|
-
// so I think it's worth the small sacrifice to memory
|
247
|
-
if (!arr?.length) {
|
248
|
-
return {}
|
249
|
-
}
|
250
|
-
|
251
|
-
return arr.reduce((acc, cur) => {
|
252
|
-
acc[cur] = true
|
253
|
-
return acc
|
254
|
-
}, {} as {[k: string]: boolean})
|
255
|
-
}
|
256
|
-
}
|
@@ -1,98 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Ariadne
|
4
|
-
# This component is part of navigation components such as `Ariadne::TabContainerComponent`.
|
5
|
-
# and `Ariadne::TabNavComponent` and should not be used by itself.
|
6
|
-
#
|
7
|
-
# @accessibility
|
8
|
-
# `TabComponent` renders the selected anchor tab with `aria-current="page"` by default.
|
9
|
-
# When the selected tab does not correspond to the current page, such as in a nested inner tab, make sure to use aria-current="true"
|
10
|
-
class TabComponent < Ariadne::Component
|
11
|
-
DEFAULT_ARIA_CURRENT_FOR_ANCHOR = :page
|
12
|
-
ARIA_CURRENT_OPTIONS_FOR_ANCHOR = [true, DEFAULT_ARIA_CURRENT_FOR_ANCHOR].freeze
|
13
|
-
|
14
|
-
# Panel controlled by the Tab. This will not render anything in the tab itself.
|
15
|
-
# It will provide a accessor for the Tab's parent to call and render the panel
|
16
|
-
# content in the appropriate place.
|
17
|
-
#
|
18
|
-
# @param classes [String] <%= link_to_classes_docs %>
|
19
|
-
# @param attributes [Hash] <%= link_to_attributes_docs %>
|
20
|
-
renders_one :panel, lambda { |classes: "", attributes: {}|
|
21
|
-
attributes[:id] = @panel_id
|
22
|
-
tag = :div
|
23
|
-
attributes[:role] ||= :tabpanel
|
24
|
-
attributes[:hidden] = true unless @selected
|
25
|
-
|
26
|
-
label_present = aria("label", attributes) || aria("labelledby", attributes)
|
27
|
-
unless label_present
|
28
|
-
if @id.present?
|
29
|
-
attributes[:"aria-labelledby"] = @id
|
30
|
-
else
|
31
|
-
raise ArgumentError, "Panels must be labelled. Either set a unique `id` on the tab, or set an `aria-label` directly on the panel"
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
Ariadne::BaseComponent.new(tag: tag, classes: classes, attributes: attributes)
|
36
|
-
}
|
37
|
-
|
38
|
-
# The tab's text.
|
39
|
-
#
|
40
|
-
# @param kwargs [Hash] The same arguments as <%= link_to_component(Ariadne::Text) %>.
|
41
|
-
renders_one :text, Ariadne::Text
|
42
|
-
# TODO: test what hapenns with really long inbox names
|
43
|
-
|
44
|
-
attr_reader :selected, :id, :classes, :attributes
|
45
|
-
|
46
|
-
DEFAULT_CLASSES = "ariadne-border-transparent ariadne-text-gray-500 hover:ariadne-text-gray-700 hover:ariadne-border-gray-300 ariadne-whitespace-nowrap ariadne-py-4 ariadne-px-1 ariadne-border-b-2 ariadne-font-medium ariadne-text-sm"
|
47
|
-
|
48
|
-
# @example Default
|
49
|
-
#
|
50
|
-
# <%= render(Ariadne::TabComponent.new(id: "pub-comment")) do |tab| %>
|
51
|
-
# <% tab.text { "Public comment" } %>
|
52
|
-
# <% tab.panel { "Public comment panel" } %>
|
53
|
-
# <% end %>
|
54
|
-
# @param id [String] The unique ID of the tab.
|
55
|
-
# @param selected [Boolean] Whether the tab is selected or not.
|
56
|
-
# @param with_panel [Boolean] Whether the Tab has an associated panel.
|
57
|
-
# @param href [String] The link to navigate to when the tab is clicked.
|
58
|
-
# @param classes [String] <%= link_to_classes_docs %>
|
59
|
-
# @param attributes [Hash] <%= link_to_attributes_docs %>
|
60
|
-
def initialize(id: nil, selected: false, with_panel: false, href: nil, classes: "", attributes: {})
|
61
|
-
@id = id
|
62
|
-
|
63
|
-
@href = href
|
64
|
-
@selected = selected
|
65
|
-
|
66
|
-
@classes = merge_class_names(
|
67
|
-
DEFAULT_CLASSES,
|
68
|
-
classes,
|
69
|
-
)
|
70
|
-
|
71
|
-
@attributes = attributes
|
72
|
-
@attributes[:id] ||= @id
|
73
|
-
|
74
|
-
if with_panel # TODO: test
|
75
|
-
if @id.blank?
|
76
|
-
raise ArgumentError, "Tabs with panels must have a unique `id`"
|
77
|
-
end
|
78
|
-
|
79
|
-
@tag = :button
|
80
|
-
@attributes[:type] = :button
|
81
|
-
@attributes[:role] = :tab
|
82
|
-
@panel_id = "panel-#{@id}"
|
83
|
-
@attributes[:"aria-controls"] = @panel_id
|
84
|
-
else
|
85
|
-
@tag = :a
|
86
|
-
end
|
87
|
-
|
88
|
-
return unless @selected
|
89
|
-
|
90
|
-
if @tag == :a
|
91
|
-
aria_current = aria("current", attributes) || DEFAULT_ARIA_CURRENT_FOR_ANCHOR
|
92
|
-
@attributes[:"aria-current"] = fetch_or_raise(ARIA_CURRENT_OPTIONS_FOR_ANCHOR, aria_current)
|
93
|
-
else
|
94
|
-
@attributes[:"aria-selected"] = true
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
@@ -1 +0,0 @@
|
|
1
|
-
import '@github/tab-container-element';
|