hakumi_components 0.1.13.pre → 0.1.15.pre

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.
@@ -70,7 +70,7 @@ module Hakumi
70
70
  # @param options [Hash] Options for the select
71
71
  # @return [String] Rendered HTML
72
72
  def select(method, choices = nil, **options)
73
- choices ||= []
73
+ choices ||= [] # steep:ignore UnannotatedEmptyCollection
74
74
  enhance_options_with_introspection!(method, options)
75
75
 
76
76
  # Get field configuration
@@ -96,7 +96,7 @@ module Hakumi
96
96
  # @param options [Hash] Options for the tree select
97
97
  # @return [String] Rendered HTML
98
98
  def tree_select(method, choices = nil, **options)
99
- choices ||= []
99
+ choices ||= [] # steep:ignore UnannotatedEmptyCollection
100
100
  enhance_options_with_introspection!(method, options)
101
101
 
102
102
  # Get field configuration
@@ -0,0 +1,151 @@
1
+ // Hakumi Components - Controller Manifest
2
+ // Add new controllers here when creating new components
3
+
4
+ // Admin & Layout
5
+ import AdminPanelController from "./controllers/hakumi/admin_panel_controller.js"
6
+ import AffixController from "./controllers/hakumi/affix_controller.js"
7
+ import AnchorController from "./controllers/hakumi/anchor_controller.js"
8
+ import BackTopController from "./controllers/hakumi/back_top_controller.js"
9
+ import SplitterController from "./controllers/hakumi/splitter_controller.js"
10
+
11
+ // Feedback
12
+ import AlertController from "./controllers/hakumi/alert_controller.js"
13
+ import DrawerController from "./controllers/hakumi/drawer_controller.js"
14
+ import MessageController from "./controllers/hakumi/message_controller.js"
15
+ import ModalController from "./controllers/hakumi/modal_controller.js"
16
+ import ModalTriggerController from "./controllers/hakumi/modal_trigger_controller.js"
17
+ import NotificationController from "./controllers/hakumi/notification_controller.js"
18
+ import PopconfirmController from "./controllers/hakumi/popconfirm_controller.js"
19
+ import PopoverController from "./controllers/hakumi/popover_controller.js"
20
+ import ProgressController from "./controllers/hakumi/progress_controller.js"
21
+ import SpinController from "./controllers/hakumi/spin_controller.js"
22
+ import TooltipController from "./controllers/hakumi/tooltip_controller.js"
23
+ import TourController from "./controllers/hakumi/tour_controller.js"
24
+
25
+ // Data Display
26
+ import AvatarTextController from "./controllers/hakumi/avatar_text_controller.js"
27
+ import CalendarController from "./controllers/hakumi/calendar_controller.js"
28
+ import CarouselController from "./controllers/hakumi/carousel_controller.js"
29
+ import CollapseController from "./controllers/hakumi/collapse_controller.js"
30
+ import ImageController from "./controllers/hakumi/image_controller.js"
31
+ import QrCodeController from "./controllers/hakumi/qr_code_controller.js"
32
+ import SegmentedController from "./controllers/hakumi/segmented_controller.js"
33
+ import StatisticController from "./controllers/hakumi/statistic_controller.js"
34
+ import TableController from "./controllers/hakumi/table_controller.js"
35
+ import TabsController from "./controllers/hakumi/tabs_controller.js"
36
+ import TagController from "./controllers/hakumi/tag_controller.js"
37
+ import TagGroupController from "./controllers/hakumi/tag_group_controller.js"
38
+ import TimelineController from "./controllers/hakumi/timeline_controller.js"
39
+ import TreeController from "./controllers/hakumi/tree_controller.js"
40
+
41
+ // Navigation
42
+ import ButtonController from "./controllers/hakumi/button_controller.js"
43
+ import DropdownController from "./controllers/hakumi/dropdown_controller.js"
44
+ import FloatButtonGroupController from "./controllers/hakumi/float_button_group_controller.js"
45
+ import MenuController from "./controllers/hakumi/menu_controller.js"
46
+ import PaginationController from "./controllers/hakumi/pagination_controller.js"
47
+ import StepsController from "./controllers/hakumi/steps_controller.js"
48
+
49
+ // Form Controls
50
+ import AutocompleteController from "./controllers/hakumi/autocomplete_controller.js"
51
+ import CascaderController from "./controllers/hakumi/cascader_controller.js"
52
+ import CheckboxController from "./controllers/hakumi/checkbox_controller.js"
53
+ import CheckboxGroupController from "./controllers/hakumi/checkbox_group_controller.js"
54
+ import ColorPickerController from "./controllers/hakumi/color_picker_controller.js"
55
+ import DatePickerController from "./controllers/hakumi/date_picker_controller.js"
56
+ import FormItemController from "./controllers/hakumi/form_item_controller.js"
57
+ import InputController from "./controllers/hakumi/input_controller.js"
58
+ import InputNumberController from "./controllers/hakumi/input_number_controller.js"
59
+ import InputPasswordController from "./controllers/hakumi/input_password_controller.js"
60
+ import InputTextareaController from "./controllers/hakumi/input_textarea_controller.js"
61
+ import MentionsController from "./controllers/hakumi/mentions_controller.js"
62
+ import RadioController from "./controllers/hakumi/radio_controller.js"
63
+ import RateController from "./controllers/hakumi/rate_controller.js"
64
+ import SelectController from "./controllers/hakumi/select_controller.js"
65
+ import SliderController from "./controllers/hakumi/slider_controller.js"
66
+ import SwitchController from "./controllers/hakumi/switch_controller.js"
67
+ import TimePickerController from "./controllers/hakumi/time_picker_controller.js"
68
+ import TransferController from "./controllers/hakumi/transfer_controller.js"
69
+ import TreeSelectController from "./controllers/hakumi/tree_select_controller.js"
70
+ import UploadController from "./controllers/hakumi/upload_controller.js"
71
+
72
+ // Typography & Theme
73
+ import ThemeController from "./controllers/hakumi/theme_controller.js"
74
+ import TypographyController from "./controllers/hakumi/typography_controller.js"
75
+
76
+ // Export controllers object
77
+ export const controllers = {
78
+ // Admin & Layout
79
+ "hakumi--admin-panel": AdminPanelController,
80
+ "hakumi--affix": AffixController,
81
+ "hakumi--anchor": AnchorController,
82
+ "hakumi--back-top": BackTopController,
83
+ "hakumi--splitter": SplitterController,
84
+
85
+ // Feedback
86
+ "hakumi--alert": AlertController,
87
+ "hakumi--drawer": DrawerController,
88
+ "hakumi--message": MessageController,
89
+ "hakumi--modal": ModalController,
90
+ "hakumi--modal-trigger": ModalTriggerController,
91
+ "hakumi--notification": NotificationController,
92
+ "hakumi--popconfirm": PopconfirmController,
93
+ "hakumi--popover": PopoverController,
94
+ "hakumi--progress": ProgressController,
95
+ "hakumi--spin": SpinController,
96
+ "hakumi--tooltip": TooltipController,
97
+ "hakumi--tour": TourController,
98
+
99
+ // Data Display
100
+ "hakumi--avatar-text": AvatarTextController,
101
+ "hakumi--calendar": CalendarController,
102
+ "hakumi--carousel": CarouselController,
103
+ "hakumi--collapse": CollapseController,
104
+ "hakumi--image": ImageController,
105
+ "hakumi--qr-code": QrCodeController,
106
+ "hakumi--segmented": SegmentedController,
107
+ "hakumi--statistic": StatisticController,
108
+ "hakumi--table": TableController,
109
+ "hakumi--tabs": TabsController,
110
+ "hakumi--tag": TagController,
111
+ "hakumi--tag-group": TagGroupController,
112
+ "hakumi--timeline": TimelineController,
113
+ "hakumi--tree": TreeController,
114
+
115
+ // Navigation
116
+ "hakumi--button": ButtonController,
117
+ "hakumi--dropdown": DropdownController,
118
+ "hakumi--float-button-group": FloatButtonGroupController,
119
+ "hakumi--menu": MenuController,
120
+ "hakumi--pagination": PaginationController,
121
+ "hakumi--steps": StepsController,
122
+
123
+ // Form Controls
124
+ "hakumi--autocomplete": AutocompleteController,
125
+ "hakumi--cascader": CascaderController,
126
+ "hakumi--checkbox": CheckboxController,
127
+ "hakumi--checkbox-group": CheckboxGroupController,
128
+ "hakumi--color-picker": ColorPickerController,
129
+ "hakumi--date-picker": DatePickerController,
130
+ "hakumi--form-item": FormItemController,
131
+ "hakumi--input": InputController,
132
+ "hakumi--input-number": InputNumberController,
133
+ "hakumi--input-password": InputPasswordController,
134
+ "hakumi--input-textarea": InputTextareaController,
135
+ "hakumi--mentions": MentionsController,
136
+ "hakumi--radio": RadioController,
137
+ "hakumi--rate": RateController,
138
+ "hakumi--select": SelectController,
139
+ "hakumi--slider": SliderController,
140
+ "hakumi--switch": SwitchController,
141
+ "hakumi--time-picker": TimePickerController,
142
+ "hakumi--transfer": TransferController,
143
+ "hakumi--tree-select": TreeSelectController,
144
+ "hakumi--upload": UploadController,
145
+
146
+ // Typography & Theme
147
+ "hakumi--theme": ThemeController,
148
+ "hakumi--typography": TypographyController,
149
+ }
150
+
151
+ export default controllers
@@ -1,5 +1,5 @@
1
1
  import RegistryController from "../base/registry_controller.js"
2
- import { Persistence } from "../../index.js"
2
+ import { Persistence } from "../../core/persistence.js"
3
3
  const STATE_LABELS = {
4
4
  open: { true: "open", false: "closed" },
5
5
  visible: { true: "visible", false: "hidden" },
@@ -1,5 +1,5 @@
1
1
  import RegistryController from "../base/registry_controller.js"
2
- import { ensureOverlayContainer } from "../../index.js"
2
+ import { ensureOverlayContainer } from "../../core/overlay_container.js"
3
3
 
4
4
  export default class extends RegistryController {
5
5
  static targets = ["mask", "wrapper", "body"]
@@ -1,5 +1,5 @@
1
1
  import RegistryController from "../base/registry_controller.js"
2
- import { ensureOverlayContainer } from "../../index.js"
2
+ import { ensureOverlayContainer } from "../../core/overlay_container.js"
3
3
 
4
4
  export default class extends RegistryController {
5
5
  static targets = ["mask", "wrapper"]
@@ -1,5 +1,5 @@
1
1
  import RegistryController from "../base/registry_controller.js"
2
- import { Persistence } from "../../index.js"
2
+ import { Persistence } from "../../core/persistence.js"
3
3
 
4
4
  const DEFAULT_DURATION = 4.5
5
5
  const NOTICE_ANIMATION_MS = 200
@@ -1,5 +1,5 @@
1
1
  import RegistryController from "../base/registry_controller.js"
2
- import { Persistence } from "../../index.js"
2
+ import { Persistence } from "../../core/persistence.js"
3
3
 
4
4
  export default class extends RegistryController {
5
5
  static values = {
@@ -0,0 +1,22 @@
1
+ // Create global overlay container for Modal, Drawer, etc.
2
+ export const ensureOverlayContainer = () => {
3
+ if (typeof document === "undefined") return null
4
+
5
+ const existingContainer = document.getElementById("hakumi-overlay-root")
6
+ if (existingContainer) return existingContainer
7
+
8
+ const container = document.createElement("div")
9
+ container.id = "hakumi-overlay-root"
10
+ container.setAttribute("data-hakumi-overlay-container", "")
11
+
12
+ // Wait for DOM to be ready
13
+ if (document.body) {
14
+ document.body.appendChild(container)
15
+ } else {
16
+ document.addEventListener("DOMContentLoaded", () => {
17
+ document.body.appendChild(container)
18
+ })
19
+ }
20
+
21
+ return container
22
+ }
@@ -2,30 +2,9 @@ import { renderComponent } from "./core/render_component.js"
2
2
  import { register, unregister, get, list } from "./core/registry.js"
3
3
  import { ensureId } from "./core/dom.js"
4
4
  import { Persistence } from "./core/persistence.js"
5
+ import { ensureOverlayContainer } from "./core/overlay_container.js"
5
6
  import DateHelper from "./utils/date_helper.js"
6
-
7
- // Create global overlay container for Modal, Drawer, etc.
8
- const ensureOverlayContainer = () => {
9
- if (typeof document === "undefined") return null
10
-
11
- const existingContainer = document.getElementById("hakumi-overlay-root")
12
- if (existingContainer) return existingContainer
13
-
14
- const container = document.createElement("div")
15
- container.id = "hakumi-overlay-root"
16
- container.setAttribute("data-hakumi-overlay-container", "")
17
-
18
- // Wait for DOM to be ready
19
- if (document.body) {
20
- document.body.appendChild(container)
21
- } else {
22
- document.addEventListener("DOMContentLoaded", () => {
23
- document.body.appendChild(container)
24
- })
25
- }
26
-
27
- return container
28
- }
7
+ import { controllers as hakumiControllers } from "./_controllers_manifest.js"
29
8
 
30
9
  export { renderComponent, register, unregister, get, list, ensureId, Persistence, ensureOverlayContainer, DateHelper }
31
10
  export { default as RegistryController } from "./controllers/base/registry_controller.js"
@@ -50,29 +29,20 @@ if (typeof window !== "undefined") {
50
29
  export const registerHakumiControllers = (application) => {
51
30
  if (!application) throw new Error("[HakumiComponents] Missing Stimulus application")
52
31
 
53
- // Use eager loading for now - Vite will handle code-splitting via manual chunks
54
- const controllers = import.meta.glob("./controllers/hakumi/**/*_controller.js", { eager: true })
55
-
56
- const classes = Object.values(controllers).map((m) => m.default).filter(Boolean)
57
-
58
- for (const C of classes) {
59
- if (typeof C.mount === "function") {
32
+ // Call mount() on controllers that support it
33
+ for (const Controller of Object.values(hakumiControllers)) {
34
+ if (typeof Controller.mount === "function") {
60
35
  try {
61
- C.mount()
36
+ Controller.mount()
62
37
  } catch (e) {
63
38
  console.error("[HakumiComponents] mount() failed", e)
64
39
  }
65
40
  }
66
41
  }
67
42
 
68
- Object.entries(controllers).forEach(([path, mod]) => {
69
- const name = path
70
- .replace("./controllers/", "")
71
- .replace("_controller.js", "")
72
- .replace(/\//g, "--")
73
- .replace(/_/g, "-")
74
-
75
- application.register(name, mod.default)
43
+ // Register all controllers with Stimulus
44
+ Object.entries(hakumiControllers).forEach(([name, Controller]) => {
45
+ application.register(name, Controller)
76
46
  })
77
47
  }
78
48
 
@@ -0,0 +1,132 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hakumi
4
+ class InstallGenerator < Rails::Generators::Base
5
+ source_root File.expand_path("templates", __dir__)
6
+
7
+ desc "Install Hakumi Components in your Rails application"
8
+
9
+ def add_npm_package
10
+ say "Adding @hakumi-dev/hakumi-components to package.json...", :green
11
+ run "yarn add @hakumi-dev/hakumi-components"
12
+ end
13
+
14
+ def setup_javascript
15
+ say "Setting up JavaScript...", :green
16
+
17
+ js_file = "app/javascript/controllers/index.js"
18
+
19
+ if File.exist?(js_file)
20
+ content = File.read(js_file)
21
+
22
+ unless content.include?("hakumi-components")
23
+ # Add import at the top
24
+ import_line = 'import { registerHakumiControllers } from "@hakumi-dev/hakumi-components"'
25
+
26
+ # Add registration after Stimulus setup
27
+ register_line = "registerHakumiControllers(application)"
28
+
29
+ # Insert import after other imports
30
+ if content.include?("import")
31
+ # Find the last import line and add after it
32
+ lines = content.split("\n")
33
+ last_import_index = lines.rindex { |line| line.start_with?("import ") }
34
+
35
+ if last_import_index
36
+ lines.insert(last_import_index + 1, import_line)
37
+ content = lines.join("\n")
38
+ end
39
+ else
40
+ content = "#{import_line}\n#{content}"
41
+ end
42
+
43
+ # Add registration at the end if not present
44
+ unless content.include?("registerHakumiControllers")
45
+ content += "\n#{register_line}\n"
46
+ end
47
+
48
+ File.write(js_file, content)
49
+ say " Updated #{js_file}", :green
50
+ else
51
+ say " #{js_file} already configured", :yellow
52
+ end
53
+ else
54
+ say " Could not find #{js_file}. Please add manually:", :yellow
55
+ say ' import { registerHakumiControllers } from "@hakumi-dev/hakumi-components"'
56
+ say " registerHakumiControllers(application)"
57
+ end
58
+ end
59
+
60
+ def setup_stylesheets
61
+ say "Setting up stylesheets...", :green
62
+
63
+ # Check for different stylesheet configurations
64
+ scss_files = [
65
+ "app/assets/stylesheets/application.scss",
66
+ "app/assets/stylesheets/application.css.scss",
67
+ "app/javascript/stylesheets/application.scss"
68
+ ]
69
+
70
+ css_files = [
71
+ "app/assets/stylesheets/application.css"
72
+ ]
73
+
74
+ scss_file = scss_files.find { |f| File.exist?(f) }
75
+ css_file = css_files.find { |f| File.exist?(f) }
76
+
77
+ if scss_file
78
+ content = File.read(scss_file)
79
+ import_line = '@import "@hakumi-dev/hakumi-components/styles";'
80
+
81
+ unless content.include?("hakumi-components")
82
+ File.write(scss_file, "#{import_line}\n#{content}")
83
+ say " Updated #{scss_file}", :green
84
+ else
85
+ say " #{scss_file} already configured", :yellow
86
+ end
87
+ elsif css_file
88
+ say " Found CSS file. For full styling support, rename to .scss and add:", :yellow
89
+ say ' @import "@hakumi-dev/hakumi-components/styles";'
90
+ else
91
+ say " Could not find stylesheet. Please add manually:", :yellow
92
+ say ' @import "@hakumi-dev/hakumi-components/styles";'
93
+ end
94
+ end
95
+
96
+ def setup_form_builder
97
+ say "Setting up FormBuilder...", :green
98
+
99
+ initializer_file = "config/initializers/hakumi_components.rb"
100
+
101
+ if File.exist?(initializer_file)
102
+ say " #{initializer_file} already exists", :yellow
103
+ else
104
+ create_file initializer_file, <<~RUBY
105
+ # frozen_string_literal: true
106
+
107
+ # Configure default form builder for Hakumi Components
108
+ Rails.application.config.action_view.default_form_builder = Hakumi::FormBuilder
109
+ RUBY
110
+ say " Created #{initializer_file}", :green
111
+ end
112
+ end
113
+
114
+ def show_post_install
115
+ say ""
116
+ say "=" * 60, :green
117
+ say "Hakumi Components installed successfully!", :green
118
+ say "=" * 60, :green
119
+ say ""
120
+ say "Next steps:"
121
+ say " 1. Restart your Rails server"
122
+ say " 2. Start using components in your views:"
123
+ say ""
124
+ say " <%= render Hakumi::Button::Component.new(type: :primary) do %>"
125
+ say " Click me"
126
+ say " <% end %>"
127
+ say ""
128
+ say "Documentation: https://github.com/hakumi-dev/hakumi-components"
129
+ say ""
130
+ end
131
+ end
132
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module HakumiComponents
4
- VERSION = "0.1.13.pre"
4
+ VERSION = "0.1.15.pre"
5
5
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hakumi
4
+ class InstallGenerator < Rails::Generators::Base
5
+ def add_npm_package: () -> void
6
+ def setup_javascript: () -> void
7
+ def setup_stylesheets: () -> void
8
+ def setup_form_builder: () -> void
9
+ def show_post_install: () -> void
10
+ end
11
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hakumi
4
+ class FormBuilder < ActionView::Helpers::FormBuilder
5
+ # Public methods - use untyped for options hash to avoid type conflicts with Rails
6
+ def text_field: (Symbol method, **untyped options) -> String
7
+ def password_field: (Symbol method, **untyped options) -> String
8
+ def text_area: (Symbol method, **untyped options) -> String
9
+ def number_field: (Symbol method, **untyped options) -> String
10
+ def radio_button: (Symbol method, untyped tag_value, **untyped options) -> String
11
+ def collection_radio_buttons: (Symbol method, untyped collection, untyped value_method, untyped text_method, **untyped options) -> String
12
+ def check_box: (Symbol method, **untyped options) -> String
13
+ def select: (Symbol method, untyped? choices, **untyped options) -> String
14
+ def tree_select: (Symbol method, untyped? choices, **untyped options) -> String
15
+ def date_picker: (Symbol method, **untyped options) -> String
16
+ def mentions_field: (Symbol method, **untyped options) -> String
17
+ def slider_field: (Symbol method, **untyped options) -> String
18
+ def rate_field: (Symbol method, **untyped options) -> String
19
+ def submit: (String? value, **untyped options) -> String
20
+
21
+ private
22
+
23
+ # Private helper methods
24
+ def enhance_options_with_introspection!: (Symbol method, Hash[Symbol, untyped] options) -> (Hash[Symbol, untyped] | nil)
25
+ def render_form_field: (Class component_class, Symbol method, **untyped options) -> String
26
+ def object_value: (Symbol method) -> untyped
27
+ def object_errors: (Symbol method) -> Array[String]
28
+ end
29
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hakumi_components
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.13.pre
4
+ version: 0.1.15.pre
5
5
  platform: ruby
6
6
  authors:
7
7
  - kb714
@@ -1109,6 +1109,7 @@ files:
1109
1109
  - app/components/hakumi/upload/component.rb
1110
1110
  - app/controllers/hakumi_components/components_controller.rb
1111
1111
  - app/form_builders/hakumi/form_builder.rb
1112
+ - app/javascript/hakumi_components/_controllers_manifest.js
1112
1113
  - app/javascript/hakumi_components/boot.js
1113
1114
  - app/javascript/hakumi_components/controllers/base/registry_controller.js
1114
1115
  - app/javascript/hakumi_components/controllers/hakumi/admin_panel_controller.js
@@ -1173,6 +1174,7 @@ files:
1173
1174
  - app/javascript/hakumi_components/controllers/hakumi/upload_controller.js
1174
1175
  - app/javascript/hakumi_components/core/config.js
1175
1176
  - app/javascript/hakumi_components/core/dom.js
1177
+ - app/javascript/hakumi_components/core/overlay_container.js
1176
1178
  - app/javascript/hakumi_components/core/persistence.js
1177
1179
  - app/javascript/hakumi_components/core/registry.js
1178
1180
  - app/javascript/hakumi_components/core/render_component.js
@@ -1276,6 +1278,7 @@ files:
1276
1278
  - app/views/hakumi_components/_tag.html.erb
1277
1279
  - app/views/hakumi_components/_timeline.html.erb
1278
1280
  - app/views/hakumi_components/_tree.html.erb
1281
+ - lib/generators/hakumi/install_generator.rb
1279
1282
  - lib/hakumi_components.rb
1280
1283
  - lib/hakumi_components/engine.rb
1281
1284
  - lib/hakumi_components/rails.rb
@@ -1284,6 +1287,7 @@ files:
1284
1287
  - lib/hakumi_components/version.rb
1285
1288
  - sig/action_view/tag_builder.rbs
1286
1289
  - sig/active_support/concern_patch.rbs
1290
+ - sig/generators/hakumi/install_generator.rbs
1287
1291
  - sig/hakumi/admin_panel/component.rbs
1288
1292
  - sig/hakumi/affix/component.rbs
1289
1293
  - sig/hakumi/alert/component.rbs
@@ -1326,6 +1330,7 @@ files:
1326
1330
  - sig/hakumi/float_button/group/component.rbs
1327
1331
  - sig/hakumi/float_button/group_cluster/component.rbs
1328
1332
  - sig/hakumi/form/item/component.rbs
1333
+ - sig/hakumi/form_builder.rbs
1329
1334
  - sig/hakumi/grid/col/component.rbs
1330
1335
  - sig/hakumi/grid/row/component.rbs
1331
1336
  - sig/hakumi/icon/component.rbs