ariadne_view_components 0.0.18 → 0.0.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +3 -0
- data/app/assets/builds/ariadne_view_components.css +2243 -0
- data/app/assets/javascripts/ariadne_view_components.js +2 -2
- data/app/assets/javascripts/ariadne_view_components.js.map +1 -1
- data/app/assets/javascripts/rich-text-area-component.d.ts +2 -0
- data/app/components/ariadne/ariadne-form-with.d.ts +20 -0
- data/app/components/ariadne/ariadne-form-with.js +85 -0
- data/app/components/ariadne/ariadne-form.d.ts +22 -0
- data/app/components/ariadne/ariadne-form.js +84 -0
- data/app/components/ariadne/ariadne.d.ts +2 -0
- data/app/components/ariadne/ariadne.js +16 -0
- data/app/components/ariadne/base_button.rb +2 -2
- data/app/components/ariadne/clipboard-copy-component.d.ts +4 -0
- data/app/components/ariadne/clipboard-copy-component.js +18 -0
- data/app/components/ariadne/clipboard_copy_component.d.ts +4 -0
- data/app/components/ariadne/clipboard_copy_component.js +18 -0
- data/app/components/ariadne/comment_component.html.erb +2 -2
- data/app/components/ariadne/component.rb +4 -0
- data/app/components/ariadne/inline_flex_component.rb +2 -2
- data/app/components/ariadne/panel_bar_component.html.erb +1 -1
- data/app/components/ariadne/panel_bar_component.rb +1 -0
- data/app/components/ariadne/rich-text-area-component.d.ts +6 -0
- data/app/components/ariadne/rich-text-area-component.js +36 -0
- data/app/components/ariadne/rich-text-area-component.ts +22 -9
- data/app/components/ariadne/rich_text_area_component.html.erb +1 -1
- data/app/components/ariadne/slideover-component.d.ts +9 -0
- data/app/components/ariadne/slideover-component.js +10 -0
- data/app/components/ariadne/slideover-component.ts +0 -9
- data/app/components/ariadne/slideover_component.d.ts +9 -0
- data/app/components/ariadne/slideover_component.html.erb +6 -8
- data/app/components/ariadne/slideover_component.js +19 -0
- data/app/components/ariadne/slideover_component.rb +9 -24
- data/app/components/ariadne/tab-component.js +1 -0
- data/app/components/ariadne/tab-container-component copy.d.ts +1 -0
- data/app/components/ariadne/tab-container-component copy.js +23 -0
- data/app/components/ariadne/tab-container-component.d.ts +1 -0
- data/app/components/ariadne/tab-container-component.js +23 -0
- data/app/components/ariadne/tab-nav-component.d.ts +9 -0
- data/app/components/ariadne/tab-nav-component.js +32 -0
- data/app/components/ariadne/tab_component.rb +0 -1
- data/app/components/ariadne/tab_container_component.erb +1 -1
- data/app/components/ariadne/tab_container_component.rb +2 -1
- data/app/components/ariadne/tabs-component.d.ts +0 -0
- data/app/components/ariadne/tabs-component.js +1 -0
- data/app/components/ariadne/time-ago-component.d.ts +1 -0
- data/app/components/ariadne/time-ago-component.js +1 -0
- data/app/components/ariadne/time_ago_component.d.ts +1 -0
- data/app/components/ariadne/time_ago_component.js +1 -0
- data/app/components/ariadne/tooltip-component.d.ts +24 -0
- data/app/components/ariadne/tooltip-component.js +42 -0
- data/lib/ariadne/view_components/version.rb +1 -1
- data/static/arguments.yml +0 -4
- data/static/classes.yml +3 -5
- data/static/constants.json +7 -8
- metadata +38 -6
@@ -0,0 +1,20 @@
|
|
1
|
+
import { Controller } from '@hotwired/stimulus';
|
2
|
+
import { TemplateResult } from 'lit-html';
|
3
|
+
declare type HTMLFormField = HTMLInputElement | HTMLButtonElement | HTMLSelectElement | HTMLTextAreaElement;
|
4
|
+
export default class AriadneFormWith extends Controller {
|
5
|
+
connect(): void;
|
6
|
+
disconnect(): void;
|
7
|
+
onBlur: (event: Event) => void;
|
8
|
+
onSubmit: (event: Event) => void;
|
9
|
+
validateForm(): boolean;
|
10
|
+
validateField(field: HTMLFormField): boolean;
|
11
|
+
shouldValidateField(field: HTMLFormField): boolean;
|
12
|
+
refreshErrorForInvalidField(field: HTMLFormField, isValid: boolean): void;
|
13
|
+
removeExistingErrorMessage(field: HTMLFormField): void;
|
14
|
+
showErrorForInvalidField(field: HTMLFormField): void;
|
15
|
+
buildFieldErrorHtml(field: HTMLFormField): string;
|
16
|
+
get formFields(): HTMLFormField[];
|
17
|
+
get firstInvalidField(): HTMLFormField | undefined;
|
18
|
+
getRenderString: (data: TemplateResult) => string;
|
19
|
+
}
|
20
|
+
export {};
|
@@ -0,0 +1,85 @@
|
|
1
|
+
import { Controller } from '@hotwired/stimulus';
|
2
|
+
import { html } from 'lit-html';
|
3
|
+
export default class AriadneFormWith extends Controller {
|
4
|
+
constructor() {
|
5
|
+
super(...arguments);
|
6
|
+
this.onBlur = (event) => {
|
7
|
+
this.validateField(event.target);
|
8
|
+
};
|
9
|
+
this.onSubmit = (event) => {
|
10
|
+
var _a;
|
11
|
+
if (!this.validateForm()) {
|
12
|
+
event.preventDefault();
|
13
|
+
(_a = this.firstInvalidField) === null || _a === void 0 ? void 0 : _a.focus();
|
14
|
+
}
|
15
|
+
};
|
16
|
+
this.getRenderString = (data) => {
|
17
|
+
const { strings, values } = data;
|
18
|
+
const v = [...values, ''].map(e => (typeof e === 'object' ? this.getRenderString(e) : e));
|
19
|
+
return strings.reduce((acc, s, i) => acc + s + v[i], '');
|
20
|
+
};
|
21
|
+
}
|
22
|
+
connect() {
|
23
|
+
this.element.setAttribute('novalidate', 'true');
|
24
|
+
this.element.addEventListener('blur', this.onBlur, true);
|
25
|
+
this.element.addEventListener('submit', this.onSubmit);
|
26
|
+
this.element.addEventListener('ajax:beforeSend', this.onSubmit);
|
27
|
+
}
|
28
|
+
disconnect() {
|
29
|
+
this.element.removeEventListener('blur', this.onBlur);
|
30
|
+
this.element.removeEventListener('submit', this.onSubmit);
|
31
|
+
this.element.removeEventListener('ajax:beforeSend', this.onSubmit);
|
32
|
+
}
|
33
|
+
validateForm() {
|
34
|
+
let isValid = true;
|
35
|
+
// Not using `find` because we want to validate all the fields
|
36
|
+
for (const field of this.formFields) {
|
37
|
+
if (this.shouldValidateField(field) && !this.validateField(field))
|
38
|
+
isValid = false;
|
39
|
+
}
|
40
|
+
return isValid;
|
41
|
+
}
|
42
|
+
validateField(field) {
|
43
|
+
if (!this.shouldValidateField(field))
|
44
|
+
return true;
|
45
|
+
const isValid = field.checkValidity();
|
46
|
+
field.classList.toggle('invalid', !isValid);
|
47
|
+
this.refreshErrorForInvalidField(field, isValid);
|
48
|
+
return isValid;
|
49
|
+
}
|
50
|
+
shouldValidateField(field) {
|
51
|
+
return !field.disabled && !['file', 'reset', 'submit', 'button'].includes(field.type);
|
52
|
+
}
|
53
|
+
refreshErrorForInvalidField(field, isValid) {
|
54
|
+
this.removeExistingErrorMessage(field);
|
55
|
+
if (!isValid)
|
56
|
+
this.showErrorForInvalidField(field);
|
57
|
+
}
|
58
|
+
removeExistingErrorMessage(field) {
|
59
|
+
var _a;
|
60
|
+
const fieldContainer = field.closest('.field');
|
61
|
+
if (!fieldContainer)
|
62
|
+
return;
|
63
|
+
const existingErrorMessageElement = fieldContainer.querySelector('.error');
|
64
|
+
if (existingErrorMessageElement) {
|
65
|
+
(_a = existingErrorMessageElement === null || existingErrorMessageElement === void 0 ? void 0 : existingErrorMessageElement.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(existingErrorMessageElement);
|
66
|
+
}
|
67
|
+
}
|
68
|
+
showErrorForInvalidField(field) {
|
69
|
+
field.insertAdjacentHTML('afterend', this.buildFieldErrorHtml(field));
|
70
|
+
}
|
71
|
+
buildFieldErrorHtml(field) {
|
72
|
+
const data = html `<p class="error">${field.validationMessage}</p>`;
|
73
|
+
return this.getRenderString(data);
|
74
|
+
}
|
75
|
+
get formFields() {
|
76
|
+
return Array.from(this.element.children).filter(node => {
|
77
|
+
const data = node.attributes.getNamedItem('data-ariadne-form-field');
|
78
|
+
if ((data === null || data === void 0 ? void 0 : data.value) === 'true')
|
79
|
+
return true;
|
80
|
+
});
|
81
|
+
}
|
82
|
+
get firstInvalidField() {
|
83
|
+
return this.formFields.find(field => !field.checkValidity());
|
84
|
+
}
|
85
|
+
}
|
@@ -0,0 +1,22 @@
|
|
1
|
+
import { Controller } from '@hotwired/stimulus';
|
2
|
+
import type { TemplateResult } from 'lit-html';
|
3
|
+
declare type HTMLFormField = HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement;
|
4
|
+
export default class AriadneFormWith extends Controller {
|
5
|
+
static targets: string[];
|
6
|
+
readonly formFieldTargets: [HTMLFormField];
|
7
|
+
connect(): void;
|
8
|
+
disconnect(): void;
|
9
|
+
onBlur: (event: Event) => void;
|
10
|
+
onSubmit: (event: Event) => void;
|
11
|
+
validateForm(): boolean;
|
12
|
+
validateField(field: HTMLFormField): boolean;
|
13
|
+
shouldValidateField(field: HTMLFormField): boolean;
|
14
|
+
refreshErrorForInvalidField(field: HTMLFormField, isValid: boolean): void;
|
15
|
+
removeExistingErrorMessage(field: HTMLFormField): void;
|
16
|
+
showErrorForInvalidField(field: HTMLFormField): void;
|
17
|
+
buildFieldErrorHtml(field: HTMLFormField): string;
|
18
|
+
get formFields(): HTMLFormField[];
|
19
|
+
get firstInvalidField(): HTMLFormField | undefined;
|
20
|
+
getRenderString: (data: TemplateResult) => string;
|
21
|
+
}
|
22
|
+
export {};
|
@@ -0,0 +1,84 @@
|
|
1
|
+
import { Controller } from '@hotwired/stimulus';
|
2
|
+
import { html } from 'lit-html';
|
3
|
+
export default class AriadneFormWith extends Controller {
|
4
|
+
constructor() {
|
5
|
+
super(...arguments);
|
6
|
+
this.onBlur = (event) => {
|
7
|
+
this.validateField(event.target);
|
8
|
+
};
|
9
|
+
this.onSubmit = (event) => {
|
10
|
+
var _a;
|
11
|
+
if (!this.validateForm()) {
|
12
|
+
event.preventDefault();
|
13
|
+
(_a = this.firstInvalidField) === null || _a === void 0 ? void 0 : _a.focus();
|
14
|
+
}
|
15
|
+
};
|
16
|
+
this.getRenderString = (data) => {
|
17
|
+
const { strings, values } = data;
|
18
|
+
const v = [...values, ''].map(e => (typeof e === 'object' ? this.getRenderString(e) : e));
|
19
|
+
return strings.reduce((acc, s, i) => acc + s + v[i], '');
|
20
|
+
};
|
21
|
+
}
|
22
|
+
connect() {
|
23
|
+
this.element.setAttribute('novalidate', 'true');
|
24
|
+
this.element.addEventListener('blur', this.onBlur, true);
|
25
|
+
this.element.addEventListener('submit', this.onSubmit);
|
26
|
+
this.element.addEventListener('ajax:beforeSend', this.onSubmit);
|
27
|
+
}
|
28
|
+
disconnect() {
|
29
|
+
this.element.removeEventListener('blur', this.onBlur);
|
30
|
+
this.element.removeEventListener('submit', this.onSubmit);
|
31
|
+
this.element.removeEventListener('ajax:beforeSend', this.onSubmit);
|
32
|
+
}
|
33
|
+
validateForm() {
|
34
|
+
let isValid = true;
|
35
|
+
// Not using `find` because we want to validate all the fields
|
36
|
+
for (const field of this.formFields) {
|
37
|
+
if (this.shouldValidateField(field) && !this.validateField(field))
|
38
|
+
isValid = false;
|
39
|
+
}
|
40
|
+
return isValid;
|
41
|
+
}
|
42
|
+
validateField(field) {
|
43
|
+
if (!this.shouldValidateField(field))
|
44
|
+
return true;
|
45
|
+
const isValid = field.checkValidity();
|
46
|
+
field.classList.toggle('invalid', !isValid);
|
47
|
+
this.refreshErrorForInvalidField(field, isValid);
|
48
|
+
return isValid;
|
49
|
+
}
|
50
|
+
shouldValidateField(field) {
|
51
|
+
return (!field.disabled &&
|
52
|
+
!field.classList.contains('ProseMirror') &&
|
53
|
+
!['file', 'reset', 'submit', 'button'].includes(field.type));
|
54
|
+
}
|
55
|
+
refreshErrorForInvalidField(field, isValid) {
|
56
|
+
this.removeExistingErrorMessage(field);
|
57
|
+
if (!isValid)
|
58
|
+
this.showErrorForInvalidField(field);
|
59
|
+
}
|
60
|
+
removeExistingErrorMessage(field) {
|
61
|
+
var _a;
|
62
|
+
const fieldContainer = field.closest('.field');
|
63
|
+
if (!fieldContainer)
|
64
|
+
return;
|
65
|
+
const existingErrorMessageElement = fieldContainer.querySelector('.error');
|
66
|
+
if (existingErrorMessageElement) {
|
67
|
+
(_a = existingErrorMessageElement === null || existingErrorMessageElement === void 0 ? void 0 : existingErrorMessageElement.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(existingErrorMessageElement);
|
68
|
+
}
|
69
|
+
}
|
70
|
+
showErrorForInvalidField(field) {
|
71
|
+
field.insertAdjacentHTML('afterend', this.buildFieldErrorHtml(field));
|
72
|
+
}
|
73
|
+
buildFieldErrorHtml(field) {
|
74
|
+
const data = html `<p class="error">${field.validationMessage}</p>`;
|
75
|
+
return this.getRenderString(data);
|
76
|
+
}
|
77
|
+
get formFields() {
|
78
|
+
return Array.from(this.formFieldTargets);
|
79
|
+
}
|
80
|
+
get firstInvalidField() {
|
81
|
+
return this.formFields.find(field => !field.checkValidity());
|
82
|
+
}
|
83
|
+
}
|
84
|
+
AriadneFormWith.targets = ['formField'];
|
@@ -0,0 +1,16 @@
|
|
1
|
+
import { Application } from '@hotwired/stimulus';
|
2
|
+
import AriadneForm from './ariadne-form';
|
3
|
+
import ClipboardCopyComponent from './clipboard-copy-component';
|
4
|
+
import RichTextAreaComponent from './rich-text-area-component';
|
5
|
+
import SlideoverComponent from './slideover-component';
|
6
|
+
import TabNavComponent from './tab-nav-component';
|
7
|
+
import TooltipComponent from './tooltip-component';
|
8
|
+
import './tab-container-component';
|
9
|
+
import './time-ago-component';
|
10
|
+
const application = Application.start();
|
11
|
+
application.register('clipboard-copy-component', ClipboardCopyComponent);
|
12
|
+
application.register('ariadne-form', AriadneForm);
|
13
|
+
application.register('rich-text-area-component', RichTextAreaComponent);
|
14
|
+
application.register('slideover-component', SlideoverComponent);
|
15
|
+
application.register('tab-nav-component', TabNavComponent);
|
16
|
+
application.register('tooltip-component', TooltipComponent);
|
@@ -19,8 +19,8 @@ module Ariadne
|
|
19
19
|
}.freeze
|
20
20
|
VALID_SIZES = SIZE_CLASS_MAPPINGS.keys.freeze
|
21
21
|
|
22
|
-
DEFAULT_CLASSES = "ariadne-
|
23
|
-
DEFAULT_NUDE_CLASSES = "
|
22
|
+
DEFAULT_CLASSES = "ariadne-items-center ariadne-border ariadne-shadow-sm focus:ariadne-outline-none focus:ariadne-ring-2 focus:ariadne-ring-offset-2"
|
23
|
+
DEFAULT_NUDE_CLASSES = "focus:ariadne-outline-none focus:ariadne-ring-2 focus:ariadne-ring-offset-2"
|
24
24
|
|
25
25
|
DEFAULT_SIZE = :md
|
26
26
|
|
@@ -0,0 +1,18 @@
|
|
1
|
+
import { Controller } from '@hotwired/stimulus';
|
2
|
+
export default class ClipboardCopyComponent extends Controller {
|
3
|
+
copy() {
|
4
|
+
const value = this.element.attributes.getNamedItem('value');
|
5
|
+
const forNode = this.element.attributes.getNamedItem('for');
|
6
|
+
if (value) {
|
7
|
+
navigator.clipboard.writeText(value.value);
|
8
|
+
}
|
9
|
+
else if (forNode) {
|
10
|
+
const node = document.getElementById(forNode.value);
|
11
|
+
navigator.clipboard.writeText((node === null || node === void 0 ? void 0 : node.textContent) || '');
|
12
|
+
}
|
13
|
+
else {
|
14
|
+
// just copy inner text
|
15
|
+
navigator.clipboard.writeText(this.element.textContent || '');
|
16
|
+
}
|
17
|
+
}
|
18
|
+
}
|
@@ -0,0 +1,18 @@
|
|
1
|
+
import { Controller } from '@hotwired/stimulus';
|
2
|
+
export default class ClipboardCopyComponent extends Controller {
|
3
|
+
copy() {
|
4
|
+
const value = this.element.attributes.getNamedItem('value');
|
5
|
+
const forNode = this.element.attributes.getNamedItem('for');
|
6
|
+
if (value) {
|
7
|
+
navigator.clipboard.writeText(value.value);
|
8
|
+
}
|
9
|
+
else if (forNode) {
|
10
|
+
const node = document.getElementById(forNode.value);
|
11
|
+
navigator.clipboard.writeText((node === null || node === void 0 ? void 0 : node.textContent) || '');
|
12
|
+
}
|
13
|
+
else {
|
14
|
+
// just copy inner text
|
15
|
+
navigator.clipboard.writeText(this.element.textContent || '');
|
16
|
+
}
|
17
|
+
}
|
18
|
+
}
|
@@ -4,7 +4,7 @@
|
|
4
4
|
<% tab.text { @public_tab_text } %>
|
5
5
|
<% tab.panel(attributes: {:"data-public" => true}) do %>
|
6
6
|
<%= ariadne_form_with(url: @url, method: @method, classes: @classes, attributes: @attributes) do |comment_box| %>
|
7
|
-
<div class="ariadne-overflow-hidden ariadne-border ariadne-border-gray-300 ariadne-shadow-sm
|
7
|
+
<div class="ariadne-overflow-hidden ariadne-border ariadne-border-gray-300 ariadne-shadow-sm">
|
8
8
|
<%= hidden_field_tag 'message_public', true %>
|
9
9
|
<%= render(Ariadne::RichTextAreaComponent.new(name: :public_bodytext, sr_label: "Select reply type", attributes: { required: true})) %>
|
10
10
|
<% comment_box.submit { @submit } %>
|
@@ -19,7 +19,7 @@
|
|
19
19
|
<% tab.text { @internal_tab_text } %>
|
20
20
|
<% tab.panel do %>
|
21
21
|
<%= ariadne_form_with(url: @url, method: @method, classes: @classes, attributes: @attributes) do |comment_box| %>
|
22
|
-
<div class="ariadne-overflow-hidden ariadne-border ariadne-border-gray-300 ariadne-shadow-sm
|
22
|
+
<div class="ariadne-overflow-hidden ariadne-border ariadne-border-gray-300 ariadne-shadow-sm">
|
23
23
|
<%= hidden_field_tag 'message_public', false %>
|
24
24
|
<%= render(Ariadne::RichTextAreaComponent.new(name: :internal_bodytext, sr_label: "Select reply type", attributes: { required: true})) %>
|
25
25
|
<% comment_box.submit { @submit } %>
|
@@ -19,6 +19,10 @@ module Ariadne
|
|
19
19
|
BASE_WRAPPER_CLASSES = "ariadne-flex ariadne-flex-col ariadne-h-screen ariadne-justify-between"
|
20
20
|
BASE_MAIN_CLASSES = "ariadne-flex-auto"
|
21
21
|
|
22
|
+
# this is defined here for the Tailwind parser to pick up; it can be useful
|
23
|
+
# in situations where hiddenness is defined by a kwarg, eg `selected: false`
|
24
|
+
BASE_HIDDEN_CLASS = "ariadne-hidden"
|
25
|
+
|
22
26
|
INVALID_ARIA_LABEL_TAGS = [:div, :span, :p].freeze
|
23
27
|
|
24
28
|
private def raise_on_invalid_options?
|
@@ -26,7 +26,7 @@ module Ariadne
|
|
26
26
|
|
27
27
|
DEFAULT_TEXT_OPEN_CLASSES = "ariadne-text-state-open"
|
28
28
|
DEFAULT_TEXT_CLOSED_CLASSES = "ariadne-text-state-closed"
|
29
|
-
DEFAULT_TEXT_CLASSES = "ariadne-pl-2 ariadne-text-sm ariadne-font-medium
|
29
|
+
DEFAULT_TEXT_CLASSES = "ariadne-pl-2 ariadne-text-sm ariadne-font-medium"
|
30
30
|
renders_one :icon, lambda { |tag: :svg, icon:, variant:, size: Ariadne::HeroiconComponent::SIZE_DEFAULT, classes: "", attributes: {}, text_classes: "", text_attributes: {}|
|
31
31
|
actual_text_classes = class_names(DEFAULT_TEXT_CLASSES, text_classes)
|
32
32
|
Ariadne::HeroiconComponent.new(tag: tag, icon: icon, variant: variant, size: size, classes: classes, attributes: attributes, text_classes: actual_text_classes, text_attributes: text_attributes) { content }
|
@@ -36,7 +36,7 @@ module Ariadne
|
|
36
36
|
Ariadne::BaseComponent.new(tag: :span, classes: classes, attributes: attributes) { content }
|
37
37
|
}
|
38
38
|
|
39
|
-
DEFAULT_LABEL_CLASSES = "ariadne-pl-2 ariadne-text-sm ariadne-font-medium
|
39
|
+
DEFAULT_LABEL_CLASSES = "ariadne-pl-2 ariadne-text-sm ariadne-font-medium"
|
40
40
|
renders_one :text, lambda { |classes: "", attributes: {}|
|
41
41
|
actual_classes = class_names(DEFAULT_LABEL_CLASSES, classes)
|
42
42
|
Ariadne::BaseComponent.new(tag: :span, classes: actual_classes, attributes: attributes) { content }
|
@@ -5,7 +5,7 @@
|
|
5
5
|
<span class="ariadne-px-6 ariadne-py-4 ariadne-flex ariadne-items-center ariadne-text-sm ariadne-font-medium">
|
6
6
|
<%= panel.icon %>
|
7
7
|
<span class="ariadne-ml-4 ariadne-text-sm ariadne-font-medium ariadne-text-gray-900"><%= panel.label %></span>
|
8
|
-
<!--
|
8
|
+
<!-- TODO: fix this -->
|
9
9
|
<% if idx + 1 < panels.size %>
|
10
10
|
<div class="md:ariadne-block ariadne-hidden ariadne-absolute ariadne-top-0 ariadne-right-0 ariadne-h-full ariadne-w-5" aria-hidden="true">
|
11
11
|
<svg class="ariadne-h-full ariadne-w-full ariadne-text-gray-300" viewBox="0 0 22 80" fill="none" preserveAspectRatio="none">
|
@@ -40,6 +40,7 @@ module Ariadne
|
|
40
40
|
DEFAULT_ITEM_CLASSES = "ariadne-relative md:ariadne-flex-1 md:ariadne-flex"
|
41
41
|
DEFAULT_WRAPPER_CLASSES = "group ariadne-flex ariadne-items-center ariadne-w-full"
|
42
42
|
|
43
|
+
# TODO: fix this
|
43
44
|
renders_one :icon, lambda { |static_content = nil, &block|
|
44
45
|
next static_content if static_content.present?
|
45
46
|
|
@@ -0,0 +1,36 @@
|
|
1
|
+
import { Controller } from '@hotwired/stimulus';
|
2
|
+
import { Editor } from '@tiptap/core';
|
3
|
+
import { Document } from '@tiptap/extension-document';
|
4
|
+
import { Paragraph } from '@tiptap/extension-paragraph';
|
5
|
+
import { Text } from '@tiptap/extension-text';
|
6
|
+
import DropCursor from '@tiptap/extension-dropcursor';
|
7
|
+
import GapCursor from '@tiptap/extension-gapcursor';
|
8
|
+
import { History } from '@tiptap/extension-history';
|
9
|
+
export default class RichTextArea extends Controller {
|
10
|
+
connect() {
|
11
|
+
for (const editorElement of this.editorTargets) {
|
12
|
+
const pmEditor = new Editor({
|
13
|
+
extensions: [DropCursor, GapCursor, History, Document, Paragraph, Text],
|
14
|
+
content: '',
|
15
|
+
injectCSS: false,
|
16
|
+
element: editorElement,
|
17
|
+
editorProps: {
|
18
|
+
attributes: {
|
19
|
+
class: 'ariadne-p-3'
|
20
|
+
}
|
21
|
+
},
|
22
|
+
parseOptions: {
|
23
|
+
preserveWhitespace: true
|
24
|
+
}
|
25
|
+
});
|
26
|
+
const tiptapValueContainer = editorElement.previousElementSibling;
|
27
|
+
if (tiptapValueContainer) {
|
28
|
+
const parentForm = editorElement.closest('form');
|
29
|
+
parentForm === null || parentForm === void 0 ? void 0 : parentForm.addEventListener('submit', () => {
|
30
|
+
tiptapValueContainer.setAttribute('value', pmEditor.getText() || '');
|
31
|
+
});
|
32
|
+
}
|
33
|
+
}
|
34
|
+
}
|
35
|
+
}
|
36
|
+
RichTextArea.targets = ['editor'];
|
@@ -1,21 +1,34 @@
|
|
1
1
|
import {Controller} from '@hotwired/stimulus'
|
2
2
|
|
3
3
|
import {Editor} from '@tiptap/core'
|
4
|
-
|
4
|
+
|
5
|
+
import {Document} from '@tiptap/extension-document'
|
6
|
+
import {Paragraph} from '@tiptap/extension-paragraph'
|
7
|
+
import {Text} from '@tiptap/extension-text'
|
8
|
+
|
9
|
+
import DropCursor from '@tiptap/extension-dropcursor'
|
10
|
+
import GapCursor from '@tiptap/extension-gapcursor'
|
11
|
+
import {History} from '@tiptap/extension-history'
|
5
12
|
|
6
13
|
export default class RichTextArea extends Controller {
|
14
|
+
static targets = ['editor']
|
15
|
+
|
16
|
+
declare readonly editorTargets: [HTMLDivElement]
|
17
|
+
|
7
18
|
connect() {
|
8
|
-
const
|
9
|
-
|
10
|
-
|
11
|
-
element: editorElement,
|
12
|
-
extensions: [StarterKit],
|
19
|
+
for (const editorElement of this.editorTargets) {
|
20
|
+
const pmEditor = new Editor({
|
21
|
+
extensions: [DropCursor, GapCursor, History, Document, Paragraph, Text],
|
13
22
|
content: '',
|
23
|
+
injectCSS: false,
|
24
|
+
element: editorElement,
|
14
25
|
editorProps: {
|
15
26
|
attributes: {
|
16
|
-
class:
|
17
|
-
'focus:ariadne-outline-none ariadne-block ariadne-w-full ariadne-resize-none ariadne-p-0 ariadne-pb-2 ariadne-border-none focus:ariadne-ring-0 sm:ariadne-text-sm'
|
27
|
+
class: 'ariadne-p-3'
|
18
28
|
}
|
29
|
+
},
|
30
|
+
parseOptions: {
|
31
|
+
preserveWhitespace: true
|
19
32
|
}
|
20
33
|
})
|
21
34
|
|
@@ -24,7 +37,7 @@ export default class RichTextArea extends Controller {
|
|
24
37
|
const parentForm = editorElement.closest('form')
|
25
38
|
|
26
39
|
parentForm?.addEventListener('submit', () => {
|
27
|
-
tiptapValueContainer.setAttribute('value',
|
40
|
+
tiptapValueContainer.setAttribute('value', pmEditor.getText() || '')
|
28
41
|
})
|
29
42
|
}
|
30
43
|
}
|
@@ -0,0 +1,9 @@
|
|
1
|
+
import { Controller } from '@hotwired/stimulus';
|
2
|
+
export default class SlideoverComponent extends Controller {
|
3
|
+
static targets: string[];
|
4
|
+
readonly expandableTarget: HTMLDivElement;
|
5
|
+
readonly expandWrapperTarget: HTMLDivElement;
|
6
|
+
readonly slidePanelTargets: [HTMLDivElement];
|
7
|
+
readonly buttonWrapperTarget: HTMLDivElement;
|
8
|
+
toggle(): void;
|
9
|
+
}
|
@@ -0,0 +1,10 @@
|
|
1
|
+
import { Controller } from '@hotwired/stimulus';
|
2
|
+
export default class SlideoverComponent extends Controller {
|
3
|
+
toggle() {
|
4
|
+
this.expandableTarget.classList.toggle('ariadne-hidden');
|
5
|
+
for (const slidePanel of this.slidePanelTargets) {
|
6
|
+
slidePanel.classList.toggle('ariadne-hidden');
|
7
|
+
}
|
8
|
+
}
|
9
|
+
}
|
10
|
+
SlideoverComponent.targets = ['expandable', 'expandWrapper', 'slidePanel', 'buttonWrapper'];
|
@@ -10,17 +10,8 @@ export default class SlideoverComponent extends Controller {
|
|
10
10
|
|
11
11
|
toggle() {
|
12
12
|
this.expandableTarget.classList.toggle('ariadne-hidden')
|
13
|
-
this.expandWrapperTarget.classList.toggle('bg-filter-panel')
|
14
13
|
for (const slidePanel of this.slidePanelTargets) {
|
15
14
|
slidePanel.classList.toggle('ariadne-hidden')
|
16
15
|
}
|
17
|
-
this.buttonWrapperTarget.classList.toggle('bg-filter-panel')
|
18
|
-
if (document.getElementById('btnClose')?.classList.contains('ariadne-hidden')) {
|
19
|
-
const formID = this.buttonWrapperTarget.getAttribute('data-slideover-component-form-id')
|
20
|
-
if (formID) {
|
21
|
-
const form = <HTMLFormElement>document.getElementById(formID)
|
22
|
-
form?.submit()
|
23
|
-
}
|
24
|
-
}
|
25
16
|
}
|
26
17
|
}
|
@@ -0,0 +1,9 @@
|
|
1
|
+
import { Controller } from '@hotwired/stimulus';
|
2
|
+
export default class SlideoverComponent extends Controller {
|
3
|
+
static targets: string[];
|
4
|
+
readonly expandableTarget: HTMLDivElement;
|
5
|
+
readonly expandWrapperTarget: HTMLDivElement;
|
6
|
+
readonly slidePanelTargets: [HTMLDivElement];
|
7
|
+
readonly buttonWrapperTarget: HTMLDivElement;
|
8
|
+
toggle(): void;
|
9
|
+
}
|
@@ -1,11 +1,9 @@
|
|
1
1
|
<%= render Ariadne::BaseComponent.new(tag: @tag, classes: @classes, attributes: @attributes) do |slideover| %>
|
2
|
-
<div data-slideover-component-target="
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
<%= close_button %>
|
9
|
-
</div>
|
2
|
+
<div data-slideover-component-target="expandable" class="ariadne-hidden ariadne-px-3">
|
3
|
+
<%= content %>
|
4
|
+
</div>
|
5
|
+
<div data-slideover-component-target="buttonWrapper" class="ariadne-relative ariadne-flex ariadne-justify-center">
|
6
|
+
<%= open_button %>
|
7
|
+
<%= close_button %>
|
10
8
|
</div>
|
11
9
|
<% end %>
|
@@ -0,0 +1,19 @@
|
|
1
|
+
import { Controller } from '@hotwired/stimulus';
|
2
|
+
export default class SlideoverComponent extends Controller {
|
3
|
+
toggle() {
|
4
|
+
var _a;
|
5
|
+
// eslint-disable-next-line no-debugger
|
6
|
+
debugger;
|
7
|
+
this.expandableTarget.classList.toggle('hidden');
|
8
|
+
this.expandWrapperTarget.classList.toggle('bg-filter-panel');
|
9
|
+
for (const slidePanel of this.slidePanelTargets) {
|
10
|
+
slidePanel.classList.toggle('hidden');
|
11
|
+
}
|
12
|
+
this.buttonWrapperTarget.classList.toggle('bg-filter-panel');
|
13
|
+
if ((_a = document.getElementById('btnClose')) === null || _a === void 0 ? void 0 : _a.classList.contains('hidden')) {
|
14
|
+
const form = this.buttonWrapperTarget.closest('form');
|
15
|
+
form === null || form === void 0 ? void 0 : form.submit();
|
16
|
+
}
|
17
|
+
}
|
18
|
+
}
|
19
|
+
SlideoverComponent.targets = ['expandable', 'expandWrapper', 'slidePanel', 'buttonWrapper'];
|