ruflet 0.0.1
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 +7 -0
- data/README.md +3 -0
- data/lib/ruflet/version.rb +5 -0
- data/lib/ruflet.rb +40 -0
- data/lib/ruflet_protocol/ruflet/protocol.rb +62 -0
- data/lib/ruflet_protocol.rb +4 -0
- data/lib/ruflet_ui/ruflet/app.rb +20 -0
- data/lib/ruflet_ui/ruflet/colors.rb +200 -0
- data/lib/ruflet_ui/ruflet/control.rb +154 -0
- data/lib/ruflet_ui/ruflet/dsl.rb +182 -0
- data/lib/ruflet_ui/ruflet/event.rb +28 -0
- data/lib/ruflet_ui/ruflet/icon_data.rb +57 -0
- data/lib/ruflet_ui/ruflet/icons/cupertino/cupertino_icons.rb +54 -0
- data/lib/ruflet_ui/ruflet/icons/cupertino_icon_lookup.rb +112 -0
- data/lib/ruflet_ui/ruflet/icons/material_icon_lookup.rb +112 -0
- data/lib/ruflet_ui/ruflet/icons/material_icons.rb +55 -0
- data/lib/ruflet_ui/ruflet/page.rb +550 -0
- data/lib/ruflet_ui/ruflet/ui/control_factory.rb +22 -0
- data/lib/ruflet_ui/ruflet/ui/control_methods.rb +16 -0
- data/lib/ruflet_ui/ruflet/ui/control_registry.rb +13 -0
- data/lib/ruflet_ui/ruflet/ui/controls/cupertino/cupertino_action_sheet_control.rb +13 -0
- data/lib/ruflet_ui/ruflet/ui/controls/cupertino/cupertino_alert_dialog_control.rb +13 -0
- data/lib/ruflet_ui/ruflet/ui/controls/cupertino/cupertino_button_control.rb +13 -0
- data/lib/ruflet_ui/ruflet/ui/controls/cupertino/cupertino_dialog_action_control.rb +13 -0
- data/lib/ruflet_ui/ruflet/ui/controls/cupertino/cupertino_filled_button_control.rb +13 -0
- data/lib/ruflet_ui/ruflet/ui/controls/cupertino/cupertino_navigation_bar_control.rb +13 -0
- data/lib/ruflet_ui/ruflet/ui/controls/cupertino/cupertino_slider_control.rb +13 -0
- data/lib/ruflet_ui/ruflet/ui/controls/cupertino/cupertino_switch_control.rb +13 -0
- data/lib/ruflet_ui/ruflet/ui/controls/cupertino/cupertino_text_field_control.rb +13 -0
- data/lib/ruflet_ui/ruflet/ui/controls/material/alert_dialog_control.rb +13 -0
- data/lib/ruflet_ui/ruflet/ui/controls/material/app_bar_control.rb +13 -0
- data/lib/ruflet_ui/ruflet/ui/controls/material/bottom_sheet_control.rb +13 -0
- data/lib/ruflet_ui/ruflet/ui/controls/material/button_control.rb +24 -0
- data/lib/ruflet_ui/ruflet/ui/controls/material/checkbox_control.rb +13 -0
- data/lib/ruflet_ui/ruflet/ui/controls/material/column_control.rb +13 -0
- data/lib/ruflet_ui/ruflet/ui/controls/material/container_control.rb +13 -0
- data/lib/ruflet_ui/ruflet/ui/controls/material/drag_target_control.rb +13 -0
- data/lib/ruflet_ui/ruflet/ui/controls/material/draggable_control.rb +13 -0
- data/lib/ruflet_ui/ruflet/ui/controls/material/elevated_button_control.rb +13 -0
- data/lib/ruflet_ui/ruflet/ui/controls/material/filled_button_control.rb +13 -0
- data/lib/ruflet_ui/ruflet/ui/controls/material/floating_action_button_control.rb +28 -0
- data/lib/ruflet_ui/ruflet/ui/controls/material/gesture_detector_control.rb +13 -0
- data/lib/ruflet_ui/ruflet/ui/controls/material/icon_button_control.rb +13 -0
- data/lib/ruflet_ui/ruflet/ui/controls/material/icon_control.rb +24 -0
- data/lib/ruflet_ui/ruflet/ui/controls/material/image_control.rb +13 -0
- data/lib/ruflet_ui/ruflet/ui/controls/material/markdown_control.rb +13 -0
- data/lib/ruflet_ui/ruflet/ui/controls/material/navigation_bar_control.rb +13 -0
- data/lib/ruflet_ui/ruflet/ui/controls/material/navigation_bar_destination_control.rb +13 -0
- data/lib/ruflet_ui/ruflet/ui/controls/material/radio_control.rb +13 -0
- data/lib/ruflet_ui/ruflet/ui/controls/material/radio_group_control.rb +13 -0
- data/lib/ruflet_ui/ruflet/ui/controls/material/row_control.rb +13 -0
- data/lib/ruflet_ui/ruflet/ui/controls/material/snack_bar_control.rb +13 -0
- data/lib/ruflet_ui/ruflet/ui/controls/material/stack_control.rb +13 -0
- data/lib/ruflet_ui/ruflet/ui/controls/material/tab_bar_control.rb +13 -0
- data/lib/ruflet_ui/ruflet/ui/controls/material/tab_bar_view_control.rb +13 -0
- data/lib/ruflet_ui/ruflet/ui/controls/material/tab_control.rb +13 -0
- data/lib/ruflet_ui/ruflet/ui/controls/material/tabs_control.rb +63 -0
- data/lib/ruflet_ui/ruflet/ui/controls/material/text_button_control.rb +13 -0
- data/lib/ruflet_ui/ruflet/ui/controls/material/text_control.rb +13 -0
- data/lib/ruflet_ui/ruflet/ui/controls/material/text_field_control.rb +13 -0
- data/lib/ruflet_ui/ruflet/ui/controls/material/view_control.rb +13 -0
- data/lib/ruflet_ui/ruflet/ui/cupertino_control_factory.rb +40 -0
- data/lib/ruflet_ui/ruflet/ui/cupertino_control_methods.rb +26 -0
- data/lib/ruflet_ui/ruflet/ui/cupertino_control_registry.rb +35 -0
- data/lib/ruflet_ui/ruflet/ui/material_control_factory.rb +94 -0
- data/lib/ruflet_ui/ruflet/ui/material_control_methods.rb +116 -0
- data/lib/ruflet_ui/ruflet/ui/material_control_registry.rb +88 -0
- data/lib/ruflet_ui/ruflet/ui/shared_control_forwarders.rb +85 -0
- data/lib/ruflet_ui/ruflet/ui/widget_builder.rb +48 -0
- data/lib/ruflet_ui.rb +112 -0
- metadata +109 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
|
|
5
|
+
module Ruflet
|
|
6
|
+
class Event
|
|
7
|
+
attr_reader :name, :target, :raw_data, :data, :page, :control
|
|
8
|
+
|
|
9
|
+
def initialize(name:, target:, raw_data:, page:, control:)
|
|
10
|
+
@name = name
|
|
11
|
+
@target = target
|
|
12
|
+
@raw_data = raw_data
|
|
13
|
+
@data = parse_data(raw_data)
|
|
14
|
+
@page = page
|
|
15
|
+
@control = control
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def parse_data(raw)
|
|
21
|
+
return raw unless raw.is_a?(String)
|
|
22
|
+
|
|
23
|
+
JSON.parse(raw)
|
|
24
|
+
rescue JSON::ParserError
|
|
25
|
+
raw
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "icons/material_icon_lookup"
|
|
4
|
+
require_relative "icons/cupertino_icon_lookup"
|
|
5
|
+
|
|
6
|
+
module Ruflet
|
|
7
|
+
class IconData
|
|
8
|
+
attr_reader :value
|
|
9
|
+
|
|
10
|
+
def initialize(value)
|
|
11
|
+
@value = normalize(value)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def ==(other)
|
|
15
|
+
other_value = other.is_a?(IconData) ? other.value : self.class.new(other).value
|
|
16
|
+
if value.is_a?(Integer) && other_value.is_a?(Integer)
|
|
17
|
+
value == other_value
|
|
18
|
+
elsif value.is_a?(String) && other_value.is_a?(String)
|
|
19
|
+
value.casecmp?(other_value)
|
|
20
|
+
else
|
|
21
|
+
value == other_value
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def eql?(other)
|
|
26
|
+
self == other
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def hash
|
|
30
|
+
value.is_a?(String) ? value.downcase.hash : value.hash
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def to_s
|
|
34
|
+
value.to_s
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
def normalize(input)
|
|
40
|
+
return input.value if input.is_a?(IconData)
|
|
41
|
+
if input.is_a?(Integer)
|
|
42
|
+
codepoint = Ruflet::MaterialIconLookup.codepoint_for(input)
|
|
43
|
+
codepoint = Ruflet::CupertinoIconLookup.codepoint_for(input) if codepoint == input
|
|
44
|
+
return codepoint
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
raw = input.to_s.strip
|
|
48
|
+
return raw if raw.empty?
|
|
49
|
+
|
|
50
|
+
codepoint = Ruflet::MaterialIconLookup.codepoint_for(raw)
|
|
51
|
+
codepoint = Ruflet::CupertinoIconLookup.codepoint_for(raw) if codepoint.nil?
|
|
52
|
+
return codepoint unless codepoint.nil?
|
|
53
|
+
|
|
54
|
+
raw
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../../icon_data"
|
|
4
|
+
require_relative "../cupertino_icon_lookup"
|
|
5
|
+
|
|
6
|
+
module Ruflet
|
|
7
|
+
module CupertinoIcons
|
|
8
|
+
module_function
|
|
9
|
+
|
|
10
|
+
ICONS = begin
|
|
11
|
+
source = Ruflet::CupertinoIconLookup.icon_map
|
|
12
|
+
if source.empty?
|
|
13
|
+
{
|
|
14
|
+
HOME: "house",
|
|
15
|
+
SEARCH: "search",
|
|
16
|
+
SETTINGS: "gear",
|
|
17
|
+
ADD: "add",
|
|
18
|
+
CLOSE: "clear"
|
|
19
|
+
}
|
|
20
|
+
else
|
|
21
|
+
source.keys.each_with_object({}) do |name, result|
|
|
22
|
+
text = name.to_s.gsub(/[^a-zA-Z0-9]/, "_").gsub(/_+/, "_").sub(/\A_/, "").sub(/_\z/, "")
|
|
23
|
+
text = "ICON_#{text}" if text.match?(/\A\d/)
|
|
24
|
+
result[text.upcase.to_sym] = name
|
|
25
|
+
end
|
|
26
|
+
end.freeze
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
ICONS.each do |const_name, icon_name|
|
|
30
|
+
next if const_defined?(const_name, false)
|
|
31
|
+
|
|
32
|
+
const_set(const_name, Ruflet::IconData.new(icon_name))
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def [](name)
|
|
36
|
+
key = name.to_s.upcase.to_sym
|
|
37
|
+
return const_get(key) if const_defined?(key, false)
|
|
38
|
+
|
|
39
|
+
Ruflet::IconData.new(name.to_s)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def all
|
|
43
|
+
ICONS.keys.map { |k| const_get(k) }
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def random
|
|
47
|
+
all.sample || Ruflet::IconData.new(Ruflet::CupertinoIconLookup.fallback_codepoint)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def names
|
|
51
|
+
ICONS.values
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Ruflet
|
|
4
|
+
module CupertinoIconLookup
|
|
5
|
+
module_function
|
|
6
|
+
|
|
7
|
+
def codepoint_for(value)
|
|
8
|
+
return value if value.is_a?(Integer)
|
|
9
|
+
|
|
10
|
+
text = value.to_s.strip
|
|
11
|
+
return nil if text.empty?
|
|
12
|
+
|
|
13
|
+
numeric = parse_numeric(text)
|
|
14
|
+
return numeric unless numeric.nil?
|
|
15
|
+
|
|
16
|
+
icons = icon_map
|
|
17
|
+
candidate_names(text).each do |name|
|
|
18
|
+
codepoint = icons[name]
|
|
19
|
+
return codepoint unless codepoint.nil?
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
nil
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def fallback_codepoint
|
|
26
|
+
icons = icon_map
|
|
27
|
+
icons["QUESTION_CIRCLE"] || icons["QUESTION"] || 0
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def icon_map
|
|
31
|
+
@icon_map ||= load_icon_map
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def candidate_names(name)
|
|
35
|
+
raw = name.to_s.strip
|
|
36
|
+
return [] if raw.empty?
|
|
37
|
+
|
|
38
|
+
underscored = raw.gsub(/\s+|-/, "_").downcase
|
|
39
|
+
stripped = underscored.sub(/\Acupertinoicons\./i, "")
|
|
40
|
+
upper = stripped.upcase
|
|
41
|
+
|
|
42
|
+
[raw, raw.upcase, underscored, stripped, upper].uniq
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def parse_numeric(text)
|
|
46
|
+
return text.to_i(16) if text.match?(/\A0x[0-9a-fA-F]+\z/)
|
|
47
|
+
return text.to_i if text.match?(/\A\d+\z/)
|
|
48
|
+
|
|
49
|
+
nil
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def load_icon_map
|
|
53
|
+
path = flet_cupertino_icons_json_file
|
|
54
|
+
if path && File.file?(path)
|
|
55
|
+
return parse_icons_json(path)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
dart_list = flet_cupertino_icons_dart_file
|
|
59
|
+
if dart_list && File.file?(dart_list)
|
|
60
|
+
return parse_flet_icons_dart(dart_list, icon_prefix: "CupertinoIcons.", set_id: 2)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
{}
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def flet_cupertino_icons_json_file
|
|
67
|
+
candidate_from_flet_checkout("sdk/python/packages/flet/src/flet/controls/cupertino/cupertino_icons.json")
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def flet_cupertino_icons_dart_file
|
|
71
|
+
candidate_from_flet_checkout("packages/flet/lib/src/utils/cupertino_icons.dart")
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def candidate_from_flet_checkout(relative_path)
|
|
75
|
+
flet_root = File.join(Dir.home, ".pub-cache", "git")
|
|
76
|
+
return nil unless Dir.exist?(flet_root)
|
|
77
|
+
|
|
78
|
+
entries = Dir.children(flet_root).select { |e| e.start_with?("flet-") }
|
|
79
|
+
return nil if entries.empty?
|
|
80
|
+
|
|
81
|
+
candidates = entries.map { |e| File.join(flet_root, e, relative_path) }.select { |p| File.file?(p) }
|
|
82
|
+
return nil if candidates.empty?
|
|
83
|
+
|
|
84
|
+
candidates.max_by { |p| File.mtime(p) rescue Time.at(0) }
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def parse_icons_json(path)
|
|
88
|
+
require "json"
|
|
89
|
+
parsed = JSON.parse(File.read(path))
|
|
90
|
+
parsed.each_with_object({}) do |(k, v), out|
|
|
91
|
+
out[k.to_s.upcase] = v.to_i
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def parse_flet_icons_dart(path, icon_prefix:, set_id:)
|
|
96
|
+
mapping = {}
|
|
97
|
+
index = 0
|
|
98
|
+
pattern = /^\s*#{Regexp.escape(icon_prefix)}([a-zA-Z0-9_]+),/
|
|
99
|
+
|
|
100
|
+
File.foreach(path) do |line|
|
|
101
|
+
next unless (match = line.match(pattern))
|
|
102
|
+
|
|
103
|
+
encoded = (set_id << 16) | index
|
|
104
|
+
mapping[match[1].upcase] = encoded
|
|
105
|
+
index += 1
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
mapping
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
end
|
|
112
|
+
end
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Ruflet
|
|
4
|
+
module MaterialIconLookup
|
|
5
|
+
module_function
|
|
6
|
+
|
|
7
|
+
def codepoint_for(value)
|
|
8
|
+
return value if value.is_a?(Integer)
|
|
9
|
+
|
|
10
|
+
text = value.to_s.strip
|
|
11
|
+
return nil if text.empty?
|
|
12
|
+
|
|
13
|
+
numeric = parse_numeric(text)
|
|
14
|
+
return numeric unless numeric.nil?
|
|
15
|
+
|
|
16
|
+
icons = icon_map
|
|
17
|
+
candidate_names(text).each do |name|
|
|
18
|
+
codepoint = icons[name]
|
|
19
|
+
return codepoint unless codepoint.nil?
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
nil
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def fallback_codepoint
|
|
26
|
+
icons = icon_map
|
|
27
|
+
icons["HELP_OUTLINE"] || icons["HELP"] || icons["QUESTION_MARK"] || 0
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def icon_map
|
|
31
|
+
@icon_map ||= load_icon_map
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def candidate_names(name)
|
|
35
|
+
raw = name.to_s.strip
|
|
36
|
+
return [] if raw.empty?
|
|
37
|
+
|
|
38
|
+
underscored = raw.gsub(/\s+|-/, "_").downcase
|
|
39
|
+
stripped = underscored.sub(/\Aicons\./, "")
|
|
40
|
+
upper = stripped.upcase
|
|
41
|
+
|
|
42
|
+
[raw, raw.upcase, underscored, stripped, upper].uniq
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def parse_numeric(text)
|
|
46
|
+
return text.to_i(16) if text.match?(/\A0x[0-9a-fA-F]+\z/)
|
|
47
|
+
return text.to_i if text.match?(/\A\d+\z/)
|
|
48
|
+
|
|
49
|
+
nil
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def load_icon_map
|
|
53
|
+
path = flet_material_icons_json_file
|
|
54
|
+
if path && File.file?(path)
|
|
55
|
+
return parse_icons_json(path)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
dart_list = flet_material_icons_dart_file
|
|
59
|
+
if dart_list && File.file?(dart_list)
|
|
60
|
+
return parse_flet_icons_dart(dart_list, icon_prefix: "Icons.", set_id: 1)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
{}
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def flet_material_icons_json_file
|
|
67
|
+
candidate_from_flet_checkout("sdk/python/packages/flet/src/flet/controls/material/icons.json")
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def flet_material_icons_dart_file
|
|
71
|
+
candidate_from_flet_checkout("packages/flet/lib/src/utils/material_icons.dart")
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def candidate_from_flet_checkout(relative_path)
|
|
75
|
+
flet_root = File.join(Dir.home, ".pub-cache", "git")
|
|
76
|
+
return nil unless Dir.exist?(flet_root)
|
|
77
|
+
|
|
78
|
+
entries = Dir.children(flet_root).select { |e| e.start_with?("flet-") }
|
|
79
|
+
return nil if entries.empty?
|
|
80
|
+
|
|
81
|
+
candidates = entries.map { |e| File.join(flet_root, e, relative_path) }.select { |p| File.file?(p) }
|
|
82
|
+
return nil if candidates.empty?
|
|
83
|
+
|
|
84
|
+
candidates.max_by { |p| File.mtime(p) rescue Time.at(0) }
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def parse_icons_json(path)
|
|
88
|
+
require "json"
|
|
89
|
+
parsed = JSON.parse(File.read(path))
|
|
90
|
+
parsed.each_with_object({}) do |(k, v), out|
|
|
91
|
+
out[k.to_s.upcase] = v.to_i
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def parse_flet_icons_dart(path, icon_prefix:, set_id:)
|
|
96
|
+
mapping = {}
|
|
97
|
+
index = 0
|
|
98
|
+
pattern = /^\s*#{Regexp.escape(icon_prefix)}([a-zA-Z0-9_]+),/
|
|
99
|
+
|
|
100
|
+
File.foreach(path) do |line|
|
|
101
|
+
next unless (match = line.match(pattern))
|
|
102
|
+
|
|
103
|
+
encoded = (set_id << 16) | index
|
|
104
|
+
mapping[match[1].upcase] = encoded
|
|
105
|
+
index += 1
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
mapping
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
end
|
|
112
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../icon_data"
|
|
4
|
+
require_relative "material_icon_lookup"
|
|
5
|
+
|
|
6
|
+
module Ruflet
|
|
7
|
+
module MaterialIcons
|
|
8
|
+
module_function
|
|
9
|
+
|
|
10
|
+
ICONS = begin
|
|
11
|
+
source = Ruflet::MaterialIconLookup.icon_map
|
|
12
|
+
if source.empty?
|
|
13
|
+
{
|
|
14
|
+
HOME: "home",
|
|
15
|
+
SETTINGS: "settings",
|
|
16
|
+
SEARCH: "search",
|
|
17
|
+
ADD: "add",
|
|
18
|
+
CLOSE: "close"
|
|
19
|
+
}
|
|
20
|
+
else
|
|
21
|
+
source.keys.each_with_object({}) do |name, result|
|
|
22
|
+
text = name.to_s.gsub(/[^a-zA-Z0-9]/, "_").gsub(/_+/, "_").sub(/\A_/, "").sub(/_\z/, "")
|
|
23
|
+
text = "ICON_#{text}" if text.match?(/\A\d/)
|
|
24
|
+
result[text.upcase.to_sym] = name
|
|
25
|
+
end
|
|
26
|
+
end.freeze
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
ICONS.each do |const_name, icon_name|
|
|
30
|
+
next if const_defined?(const_name, false)
|
|
31
|
+
|
|
32
|
+
const_set(const_name, Ruflet::IconData.new(icon_name))
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def [](name)
|
|
36
|
+
key = name.to_s.upcase.to_sym
|
|
37
|
+
return const_get(key) if const_defined?(key, false)
|
|
38
|
+
|
|
39
|
+
Ruflet::IconData.new(name.to_s)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def all
|
|
43
|
+
ICONS.keys.map { |k| const_get(k) }
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def random
|
|
47
|
+
all.sample || Ruflet::IconData.new(Ruflet::MaterialIconLookup.fallback_codepoint)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def names
|
|
51
|
+
ICONS.values
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
end
|
|
55
|
+
end
|