shimmer 0.0.18 → 0.0.21
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/.vscode/settings.json +1 -0
- data/lib/shimmer/form/builder.rb +88 -0
- data/lib/shimmer/form/checkboxes_field.rb +13 -0
- data/lib/shimmer/form/date_field.rb +13 -0
- data/lib/shimmer/form/email_field.rb +19 -0
- data/lib/shimmer/form/field.rb +26 -0
- data/lib/shimmer/form/number_field.rb +13 -0
- data/lib/shimmer/form/password_field.rb +19 -0
- data/lib/shimmer/form/pdf_field.rb +19 -0
- data/lib/shimmer/form/radio_field.rb +13 -0
- data/lib/shimmer/form/select_field.rb +19 -0
- data/lib/shimmer/form/text_area_field.rb +13 -0
- data/lib/shimmer/form/text_field.rb +13 -0
- data/lib/shimmer/form/time_field.rb +13 -0
- data/lib/shimmer/form.rb +16 -0
- data/lib/shimmer/utils/consent_settings.rb +41 -0
- data/lib/shimmer/version.rb +1 -1
- data/lib/shimmer.rb +1 -0
- data/src/consent.ts +64 -0
- data/src/controllers/analytics.ts +42 -0
- data/src/controllers/consent.ts +52 -0
- data/src/index.ts +14 -4
- data/src/util.ts +19 -0
- metadata +20 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 89571a33faa2d1fd1d8c9624ab42a51f019418efc9c91af68fb3bb0385b5f602
|
4
|
+
data.tar.gz: 814bca1dbd13b0e147df173b1b41077c0c585f4bd5b8e1b9e6933051d597f231
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6d1c9bfa6f442914ca03747cf391ebf52086cb2c92d334641715031539cef826f09e171d3510e20866780ed87a1829182872485f6cd143c833ddebab97e1abf8
|
7
|
+
data.tar.gz: 5db21bb6096a9a4a555b17c05d2ba128379f049ed87bae1e9fd9cddf824a05214c9858d8760924ea948d11645f9052b3d503167a098ece2ba97fb5ca498db754
|
data/.vscode/settings.json
CHANGED
@@ -0,0 +1,88 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Shimmer
|
4
|
+
module Form
|
5
|
+
class Builder < ActionView::Helpers::FormBuilder
|
6
|
+
class << self
|
7
|
+
def input_registry
|
8
|
+
@input_registry ||= {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def register(klass)
|
12
|
+
input_registry[klass.type] = klass
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def input(method, as: guess_type(method), **options)
|
17
|
+
as ||= guess_type(method)
|
18
|
+
options[:class] ||= "input__input"
|
19
|
+
collection = options.delete :collection
|
20
|
+
collection_based = !collection.nil? || as == :select
|
21
|
+
collection ||= guess_collection(method) if collection_based
|
22
|
+
name_method ||= guess_name_method(method) if collection_based
|
23
|
+
id_method ||= :id if collection_based
|
24
|
+
classes = []
|
25
|
+
options[:required] ||= true if options[:required].nil? && required_attributes.include?(method)
|
26
|
+
options[:data] ||= {}
|
27
|
+
options[:data][:controller] = options.delete(:controller) if options[:controller]
|
28
|
+
wrapper_data = {}
|
29
|
+
extra = []
|
30
|
+
input_class = self.class.input_registry[as]
|
31
|
+
raise "Unknown type #{as}" unless input_class
|
32
|
+
input = input_class.new(builder: self, method: method, options: options, id_method: id_method, collection: collection, name_method: name_method)
|
33
|
+
wrap method: method, content: input.render, classes: classes + ["input--#{as}"], label: options[:label], data: wrapper_data, extra: extra
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def required_attributes
|
39
|
+
[]
|
40
|
+
end
|
41
|
+
|
42
|
+
def guess_type(method)
|
43
|
+
self.class.input_registry.values.find { |e| e.can_handle?(method) }&.type || :string
|
44
|
+
end
|
45
|
+
|
46
|
+
def guess_collection(method)
|
47
|
+
association_for(method)&.klass&.all || enum_for(method).map { |e| OpenStruct.new(id: e, name: e) } || []
|
48
|
+
end
|
49
|
+
|
50
|
+
def guess_name_method(method)
|
51
|
+
klass = association_for(method)&.klass
|
52
|
+
return :name unless klass
|
53
|
+
|
54
|
+
[:display_name, :name, :title].each do |key|
|
55
|
+
return key if klass.instance_methods.include?(key)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def association_for(method)
|
60
|
+
collection_method = method.to_s.delete_suffix("_id")
|
61
|
+
object.class.reflect_on_association(collection_method) if object.respond_to?(collection_method)
|
62
|
+
end
|
63
|
+
|
64
|
+
def enum_for(method)
|
65
|
+
object.class.types.keys if object.class.respond_to?(method.to_s.pluralize)
|
66
|
+
end
|
67
|
+
|
68
|
+
def wrap(method:, content:, classes:, label:, data: nil, extra: nil)
|
69
|
+
if object&.errors&.[](method)&.any?
|
70
|
+
classes << "input--error"
|
71
|
+
errors = safe_join(object.errors[method].map { |e| content_tag :div, e, class: "input__error" })
|
72
|
+
end
|
73
|
+
label = label == false ? nil : self.label(method, label, class: "input__label")
|
74
|
+
content_tag(:div, safe_join([label, content, errors, extra].compact), class: ["input"] + classes, data: data)
|
75
|
+
end
|
76
|
+
|
77
|
+
def helper
|
78
|
+
@template
|
79
|
+
end
|
80
|
+
|
81
|
+
def value_for(method)
|
82
|
+
object.public_send(method)
|
83
|
+
end
|
84
|
+
|
85
|
+
delegate :content_tag, :t, :safe_join, :icon, :tag, to: :helper
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Shimmer
|
4
|
+
module Form
|
5
|
+
class EmailField < Field
|
6
|
+
self.type = :email
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def can_handle?(method)
|
10
|
+
method.to_s.end_with?("email")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def render
|
15
|
+
builder.email_field method, options
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Shimmer
|
4
|
+
module Form
|
5
|
+
class Field
|
6
|
+
class_attribute :type
|
7
|
+
|
8
|
+
attr_reader :builder, :method, :collection, :id_method, :name_method, :options
|
9
|
+
|
10
|
+
class << self
|
11
|
+
def can_handle?(method)
|
12
|
+
false
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(builder:, method:, collection:, id_method:, name_method:, options: {})
|
17
|
+
@builder = builder
|
18
|
+
@method = method
|
19
|
+
@collection = collection
|
20
|
+
@id_method = id_method
|
21
|
+
@name_method = name_method
|
22
|
+
@options = options
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Shimmer
|
4
|
+
module Form
|
5
|
+
class PasswordField < Field
|
6
|
+
self.type = :password
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def can_handle?(method)
|
10
|
+
method.to_s.end_with?("password")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def render
|
15
|
+
builder.password_field method, options
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Shimmer
|
4
|
+
module Form
|
5
|
+
class PdfField < Field
|
6
|
+
self.type = :pdf
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def can_handle?(method)
|
10
|
+
method.to_s.end_with?("pdf")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def render
|
15
|
+
builder.file_field method, options.reverse_merge(accept: "application/pdf")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Shimmer
|
4
|
+
module Form
|
5
|
+
class SelectField < Field
|
6
|
+
self.type = :select
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def can_handle?(method)
|
10
|
+
method.to_s.end_with?("_id")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def render
|
15
|
+
builder.collection_select method, collection, id_method, name_method, {}, options
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/shimmer/form.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Shimmer
|
4
|
+
module Form
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
require_relative "./form/builder"
|
9
|
+
require_relative "./form/field"
|
10
|
+
|
11
|
+
Dir["#{File.expand_path("./form", __dir__)}/*"].sort.each do |e|
|
12
|
+
require e
|
13
|
+
name = e.split("/").last.delete_suffix(".rb")
|
14
|
+
next unless name.end_with?("_field")
|
15
|
+
Shimmer::Form::Builder.register("Shimmer::Form::#{name.classify}".constantize)
|
16
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Shimmer
|
4
|
+
class ConsentSettings
|
5
|
+
SETTINGS = [:essential, :targeting, :statistic].freeze
|
6
|
+
DEFAULT = [:essential].freeze
|
7
|
+
|
8
|
+
SETTINGS.each do |setting|
|
9
|
+
attr_accessor setting
|
10
|
+
alias_method "#{setting}?", setting
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(cookies)
|
14
|
+
@cookies = cookies
|
15
|
+
allowed = @cookies[:consent].to_s.split(",").map(&:strip)
|
16
|
+
SETTINGS.each do |setting|
|
17
|
+
instance_variable_set "@#{setting}", DEFAULT.include?(setting) || allowed.include?(setting.to_s)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def save
|
22
|
+
value = SETTINGS.map { |e| e.to_s if instance_variable_get("@#{e}") }.compact.join(",")
|
23
|
+
@cookies.permanent[:consent] = {value: value, expires: 2.years.from_now}
|
24
|
+
end
|
25
|
+
|
26
|
+
def given?
|
27
|
+
@cookies[:consent].present?
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
module Consent
|
32
|
+
extend ActiveSupport::Concern
|
33
|
+
|
34
|
+
included do
|
35
|
+
helper_method :consent_settings
|
36
|
+
def consent_settings
|
37
|
+
@consent_settings ||= ConsentSettings.new(cookies)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/shimmer/version.rb
CHANGED
data/lib/shimmer.rb
CHANGED
@@ -7,6 +7,7 @@ Dir["#{File.expand_path("../lib/shimmer/controllers", __dir__)}/*"].sort.each {
|
|
7
7
|
Dir["#{File.expand_path("../lib/shimmer/jobs", __dir__)}/*"].sort.each { |e| require e }
|
8
8
|
Dir["#{File.expand_path("../lib/shimmer/utils", __dir__)}/*"].sort.each { |e| require e }
|
9
9
|
require_relative "shimmer/auth"
|
10
|
+
require_relative "shimmer/form"
|
10
11
|
|
11
12
|
module Shimmer
|
12
13
|
class Error < StandardError; end
|
data/src/consent.ts
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
import { getCookie, setCookie } from "./util";
|
2
|
+
|
3
|
+
const consentCategories = ["essential", "targeting", "statistic"] as const;
|
4
|
+
export type ConsentCategory = typeof consentCategories[number];
|
5
|
+
|
6
|
+
export class Consent {
|
7
|
+
#consentListeners: Record<ConsentCategory, Array<() => void>> = {
|
8
|
+
essential: [],
|
9
|
+
targeting: [],
|
10
|
+
statistic: [],
|
11
|
+
};
|
12
|
+
|
13
|
+
get permitted(): ConsentCategory[] {
|
14
|
+
return (getCookie("consent") ?? "").split(",") as ConsentCategory[];
|
15
|
+
}
|
16
|
+
|
17
|
+
set permitted(settings: ConsentCategory[]) {
|
18
|
+
setCookie("consent", settings.join(","));
|
19
|
+
settings.forEach((category) => {
|
20
|
+
this.#consentListeners[category].forEach((e) => e());
|
21
|
+
});
|
22
|
+
}
|
23
|
+
|
24
|
+
get given(): boolean {
|
25
|
+
return getCookie("consent") !== undefined;
|
26
|
+
}
|
27
|
+
|
28
|
+
permitAll(): void {
|
29
|
+
this.permitted = consentCategories.slice();
|
30
|
+
}
|
31
|
+
|
32
|
+
denyAll(): void {
|
33
|
+
this.permitted = ["essential"];
|
34
|
+
}
|
35
|
+
|
36
|
+
showSettings(): void {
|
37
|
+
const element = document.getElementById("personalization-settings");
|
38
|
+
if (element) element.hidden = false;
|
39
|
+
}
|
40
|
+
|
41
|
+
consentFor(category: ConsentCategory): Promise<void> {
|
42
|
+
return new Promise((res) => {
|
43
|
+
if (this.permitted.includes(category)) {
|
44
|
+
res();
|
45
|
+
} else {
|
46
|
+
this.#consentListeners[category].push(res);
|
47
|
+
}
|
48
|
+
});
|
49
|
+
}
|
50
|
+
|
51
|
+
async enableGoogleAnalytics(
|
52
|
+
id: string,
|
53
|
+
role: ConsentCategory = "statistic"
|
54
|
+
): Promise<void> {
|
55
|
+
await this.consentFor(role);
|
56
|
+
window.gtag("config", id);
|
57
|
+
const script = document.createElement("script");
|
58
|
+
script.setAttribute(
|
59
|
+
"src",
|
60
|
+
`https://www.googletagmanager.com/gtag/js?id=${id}`
|
61
|
+
);
|
62
|
+
document.head.appendChild(script);
|
63
|
+
}
|
64
|
+
}
|
@@ -0,0 +1,42 @@
|
|
1
|
+
import { Controller } from "@hotwired/stimulus";
|
2
|
+
|
3
|
+
interface DataEvent {
|
4
|
+
event: string;
|
5
|
+
}
|
6
|
+
|
7
|
+
declare global {
|
8
|
+
interface Window {
|
9
|
+
dataLayer?: DataEvent[];
|
10
|
+
gtag(...arg): void;
|
11
|
+
}
|
12
|
+
}
|
13
|
+
|
14
|
+
const dataLayer = (window.dataLayer = window.dataLayer ?? []);
|
15
|
+
|
16
|
+
window.gtag = (...arg) => {
|
17
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
18
|
+
dataLayer.push(arg as any);
|
19
|
+
};
|
20
|
+
window.gtag("js", new Date());
|
21
|
+
|
22
|
+
export default class extends Controller {
|
23
|
+
connect(): void {
|
24
|
+
this.recordPage();
|
25
|
+
}
|
26
|
+
|
27
|
+
recordAction(event: MouseEvent): void {
|
28
|
+
const data = JSON.parse(
|
29
|
+
(event.target as HTMLElement).dataset.analytics ?? "{}"
|
30
|
+
);
|
31
|
+
dataLayer.push(data);
|
32
|
+
}
|
33
|
+
|
34
|
+
recordPage(): void {
|
35
|
+
const event = {
|
36
|
+
event: "Pageview",
|
37
|
+
path: location.pathname + location.search,
|
38
|
+
host: location.host,
|
39
|
+
};
|
40
|
+
dataLayer.push(event);
|
41
|
+
}
|
42
|
+
}
|
@@ -0,0 +1,52 @@
|
|
1
|
+
import { Controller } from "@hotwired/stimulus";
|
2
|
+
import { ConsentCategory } from "../consent";
|
3
|
+
|
4
|
+
export default class extends Controller {
|
5
|
+
static targets = ["check"];
|
6
|
+
declare checkTargets: HTMLInputElement[];
|
7
|
+
|
8
|
+
connect(): void {
|
9
|
+
this.checkTargets.forEach((input) => {
|
10
|
+
input.checked =
|
11
|
+
window.ui?.consent.permitted.includes(input.name as ConsentCategory) ||
|
12
|
+
input.name === "essential";
|
13
|
+
});
|
14
|
+
}
|
15
|
+
|
16
|
+
permitAll(event: Event): void {
|
17
|
+
event.preventDefault();
|
18
|
+
window.ui?.consent.permitAll();
|
19
|
+
this.closeAll();
|
20
|
+
}
|
21
|
+
|
22
|
+
denyAll(event: Event): void {
|
23
|
+
event.preventDefault();
|
24
|
+
window.ui?.consent.denyAll();
|
25
|
+
this.closeAll();
|
26
|
+
}
|
27
|
+
|
28
|
+
save(event: Event): void {
|
29
|
+
event.preventDefault();
|
30
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
31
|
+
window.ui!.consent.permitted = this.checkTargets
|
32
|
+
.filter((e) => e.checked)
|
33
|
+
.map((e) => e.name) as ConsentCategory[];
|
34
|
+
this.closeAll();
|
35
|
+
}
|
36
|
+
|
37
|
+
manage(event: Event): void {
|
38
|
+
event.preventDefault();
|
39
|
+
const div = document.body.querySelector(
|
40
|
+
"#personalization-settings"
|
41
|
+
) as HTMLDivElement;
|
42
|
+
if (!div) return;
|
43
|
+
(this.element as HTMLElement).hidden = true;
|
44
|
+
div.hidden = false;
|
45
|
+
}
|
46
|
+
|
47
|
+
closeAll(): void {
|
48
|
+
document
|
49
|
+
.querySelectorAll("[data-controller='consent']")
|
50
|
+
.forEach((e: HTMLElement) => (e.hidden = true));
|
51
|
+
}
|
52
|
+
}
|
data/src/index.ts
CHANGED
@@ -1,7 +1,10 @@
|
|
1
1
|
import type { Application } from "@hotwired/stimulus";
|
2
2
|
import { ModalPresenter } from "./modal";
|
3
3
|
import { PopoverPresenter } from "./popover";
|
4
|
+
import { Consent } from "./consent";
|
4
5
|
import RemoteNavigationController from "./controllers/remote-navigation";
|
6
|
+
import ConsentController from "./controllers/consent";
|
7
|
+
import AnalyticsController from "./controllers/analytics";
|
5
8
|
import "./touch";
|
6
9
|
|
7
10
|
export { registerServiceWorker } from "./serviceworker";
|
@@ -12,10 +15,17 @@ declare global {
|
|
12
15
|
ui?: {
|
13
16
|
modal: ModalPresenter;
|
14
17
|
popover: PopoverPresenter;
|
18
|
+
consent: Consent;
|
15
19
|
};
|
16
20
|
}
|
17
21
|
}
|
18
22
|
|
23
|
+
window.ui = {
|
24
|
+
modal: new ModalPresenter(),
|
25
|
+
popover: new PopoverPresenter(),
|
26
|
+
consent: new Consent(),
|
27
|
+
};
|
28
|
+
|
19
29
|
function createRemoteDestination(): void {
|
20
30
|
if (document.getElementById("shimmer")) {
|
21
31
|
return;
|
@@ -33,8 +43,8 @@ export async function start({
|
|
33
43
|
window.addEventListener("turbo:load", createRemoteDestination);
|
34
44
|
createRemoteDestination();
|
35
45
|
application.register("remote-navigation", RemoteNavigationController);
|
36
|
-
|
37
|
-
|
38
|
-
popover: new PopoverPresenter(),
|
39
|
-
};
|
46
|
+
application.register("consent", ConsentController);
|
47
|
+
application.register("analytics", AnalyticsController);
|
40
48
|
}
|
49
|
+
|
50
|
+
export const ui = window.ui;
|
data/src/util.ts
CHANGED
@@ -44,3 +44,22 @@ export function wait(seconds: number): Promise<void> {
|
|
44
44
|
setTimeout(res, seconds * 1000);
|
45
45
|
});
|
46
46
|
}
|
47
|
+
|
48
|
+
export function getCookie(key: string): string | null {
|
49
|
+
if (!document.cookie) return null;
|
50
|
+
return (
|
51
|
+
document.cookie
|
52
|
+
.split(";")
|
53
|
+
.map((v) => v.split("="))
|
54
|
+
.reduce((acc, v) => {
|
55
|
+
acc[decodeURIComponent(v[0].trim())] = decodeURIComponent(v[1].trim());
|
56
|
+
return acc;
|
57
|
+
}, {})[key] ?? null
|
58
|
+
);
|
59
|
+
}
|
60
|
+
|
61
|
+
export function setCookie(key: string, value: string): void {
|
62
|
+
const date = new Date();
|
63
|
+
date.setTime(date.getTime() + 365 * 24 * 60 * 60 * 1000);
|
64
|
+
document.cookie = `${key}=${value}; expires=${date.toUTCString()}`;
|
65
|
+
}
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: shimmer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.21
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jens Ravens
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-08-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -145,6 +145,20 @@ files:
|
|
145
145
|
- lib/shimmer/auth/user.rb
|
146
146
|
- lib/shimmer/controllers/files_controller.rb
|
147
147
|
- lib/shimmer/controllers/sitemaps_controller.rb
|
148
|
+
- lib/shimmer/form.rb
|
149
|
+
- lib/shimmer/form/builder.rb
|
150
|
+
- lib/shimmer/form/checkboxes_field.rb
|
151
|
+
- lib/shimmer/form/date_field.rb
|
152
|
+
- lib/shimmer/form/email_field.rb
|
153
|
+
- lib/shimmer/form/field.rb
|
154
|
+
- lib/shimmer/form/number_field.rb
|
155
|
+
- lib/shimmer/form/password_field.rb
|
156
|
+
- lib/shimmer/form/pdf_field.rb
|
157
|
+
- lib/shimmer/form/radio_field.rb
|
158
|
+
- lib/shimmer/form/select_field.rb
|
159
|
+
- lib/shimmer/form/text_area_field.rb
|
160
|
+
- lib/shimmer/form/text_field.rb
|
161
|
+
- lib/shimmer/form/time_field.rb
|
148
162
|
- lib/shimmer/helpers/meta_helper.rb
|
149
163
|
- lib/shimmer/jobs/sitemap_job.rb
|
150
164
|
- lib/shimmer/middlewares/cloudflare.rb
|
@@ -154,6 +168,7 @@ files:
|
|
154
168
|
- lib/shimmer/tasks/lint.rake
|
155
169
|
- lib/shimmer/tasks/s3.rake
|
156
170
|
- lib/shimmer/utils/config.rb
|
171
|
+
- lib/shimmer/utils/consent_settings.rb
|
157
172
|
- lib/shimmer/utils/file_helper.rb
|
158
173
|
- lib/shimmer/utils/file_proxy.rb
|
159
174
|
- lib/shimmer/utils/localizable.rb
|
@@ -163,6 +178,9 @@ files:
|
|
163
178
|
- lib/shimmer/version.rb
|
164
179
|
- package.json
|
165
180
|
- rollup.config.js
|
181
|
+
- src/consent.ts
|
182
|
+
- src/controllers/analytics.ts
|
183
|
+
- src/controllers/consent.ts
|
166
184
|
- src/controllers/remote-navigation.ts
|
167
185
|
- src/index.ts
|
168
186
|
- src/locale.ts
|