fron-ui 1.0.0rc2

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.
Files changed (140) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +3 -0
  3. data/.rubocop.yml +38 -0
  4. data/.ruby-gemset +1 -0
  5. data/.ruby-version +1 -0
  6. data/.travis.yml +7 -0
  7. data/.yardopts +8 -0
  8. data/Gemfile +8 -0
  9. data/Gemfile.lock +105 -0
  10. data/Rakefile +37 -0
  11. data/Readme.md +4 -0
  12. data/db.json +192 -0
  13. data/fron-ui.gemspec +21 -0
  14. data/lib/fron-ui.rb +1 -0
  15. data/lib/fron_ui.rb +5 -0
  16. data/lib/fron_ui/version.rb +7 -0
  17. data/opal/fron-ui/base.rb +49 -0
  18. data/opal/fron-ui/behaviors/action.rb +40 -0
  19. data/opal/fron-ui/behaviors/actions.rb +40 -0
  20. data/opal/fron-ui/behaviors/confirmation.rb +23 -0
  21. data/opal/fron-ui/behaviors/dropdown.rb +27 -0
  22. data/opal/fron-ui/behaviors/file.rb +48 -0
  23. data/opal/fron-ui/behaviors/intendable_children.rb +76 -0
  24. data/opal/fron-ui/behaviors/keydown.rb +31 -0
  25. data/opal/fron-ui/behaviors/loop.rb +41 -0
  26. data/opal/fron-ui/behaviors/render.rb +30 -0
  27. data/opal/fron-ui/behaviors/rest.rb +121 -0
  28. data/opal/fron-ui/behaviors/selectable_children.rb +67 -0
  29. data/opal/fron-ui/behaviors/serialize.rb +32 -0
  30. data/opal/fron-ui/behaviors/shortcuts.rb +35 -0
  31. data/opal/fron-ui/behaviors/state.rb +56 -0
  32. data/opal/fron-ui/behaviors/transition.rb +63 -0
  33. data/opal/fron-ui/components/action.rb +18 -0
  34. data/opal/fron-ui/components/box.rb +17 -0
  35. data/opal/fron-ui/components/button.rb +61 -0
  36. data/opal/fron-ui/components/calendar.rb +129 -0
  37. data/opal/fron-ui/components/checkbox.rb +57 -0
  38. data/opal/fron-ui/components/chooser.rb +246 -0
  39. data/opal/fron-ui/components/color_panel.rb +235 -0
  40. data/opal/fron-ui/components/color_picker.rb +111 -0
  41. data/opal/fron-ui/components/container.rb +61 -0
  42. data/opal/fron-ui/components/date_picker.rb +141 -0
  43. data/opal/fron-ui/components/drag.rb +76 -0
  44. data/opal/fron-ui/components/dropdown.rb +72 -0
  45. data/opal/fron-ui/components/icon.rb +29 -0
  46. data/opal/fron-ui/components/image.rb +77 -0
  47. data/opal/fron-ui/components/input.rb +30 -0
  48. data/opal/fron-ui/components/label.rb +9 -0
  49. data/opal/fron-ui/components/list.rb +34 -0
  50. data/opal/fron-ui/components/loader.rb +63 -0
  51. data/opal/fron-ui/components/modal.rb +0 -0
  52. data/opal/fron-ui/components/notifications.rb +73 -0
  53. data/opal/fron-ui/components/number.rb +202 -0
  54. data/opal/fron-ui/components/progress.rb +52 -0
  55. data/opal/fron-ui/components/slider.rb +47 -0
  56. data/opal/fron-ui/components/tabs.rb +149 -0
  57. data/opal/fron-ui/components/textarea.rb +13 -0
  58. data/opal/fron-ui/components/time.rb +65 -0
  59. data/opal/fron-ui/components/title.rb +34 -0
  60. data/opal/fron-ui/examples/blog/index.rb +289 -0
  61. data/opal/fron-ui/examples/comments/components/comment.rb +75 -0
  62. data/opal/fron-ui/examples/comments/components/comments.rb +93 -0
  63. data/opal/fron-ui/examples/comments/components/footer.rb +36 -0
  64. data/opal/fron-ui/examples/comments/components/header.rb +35 -0
  65. data/opal/fron-ui/examples/comments/components/list.rb +12 -0
  66. data/opal/fron-ui/examples/comments/index.rb +6 -0
  67. data/opal/fron-ui/examples/contacts/components/contacts.rb +100 -0
  68. data/opal/fron-ui/examples/contacts/components/details.rb +92 -0
  69. data/opal/fron-ui/examples/contacts/components/item.rb +46 -0
  70. data/opal/fron-ui/examples/contacts/components/list.rb +10 -0
  71. data/opal/fron-ui/examples/contacts/components/sidebar.rb +30 -0
  72. data/opal/fron-ui/examples/contacts/index.rb +6 -0
  73. data/opal/fron-ui/examples/editor/index.rb +164 -0
  74. data/opal/fron-ui/examples/kitchensink/index.rb +193 -0
  75. data/opal/fron-ui/examples/todos/components/item.rb +84 -0
  76. data/opal/fron-ui/examples/todos/components/options.rb +26 -0
  77. data/opal/fron-ui/examples/todos/components/todos.rb +145 -0
  78. data/opal/fron-ui/examples/todos/index.rb +6 -0
  79. data/opal/fron-ui/examples/webshop/index.rb +0 -0
  80. data/opal/fron-ui/fonts/ionicons.rb +2954 -0
  81. data/opal/fron-ui/fonts/open_sans.rb +19 -0
  82. data/opal/fron-ui/lib/collection.rb +138 -0
  83. data/opal/fron-ui/lib/date.rb +23 -0
  84. data/opal/fron-ui/lib/debounce.rb +14 -0
  85. data/opal/fron-ui/lib/image_loader.rb +13 -0
  86. data/opal/fron-ui/lib/lorem.rb +93 -0
  87. data/opal/fron-ui/lib/nil.rb +29 -0
  88. data/opal/fron-ui/lib/record.rb +23 -0
  89. data/opal/fron-ui/lib/state_serializer.rb +129 -0
  90. data/opal/fron-ui/lib/storage.rb +57 -0
  91. data/opal/fron-ui/spec/setup.rb +40 -0
  92. data/opal/fron-ui/ui.rb +40 -0
  93. data/opal/fron-ui/utils/theme_roller.rb +63 -0
  94. data/opal/fron-ui/vendor/autoprefixer.js +21114 -0
  95. data/opal/fron-ui/vendor/marked.js +1291 -0
  96. data/opal/fron-ui/vendor/md5.js +274 -0
  97. data/opal/fron-ui/vendor/moment.js +3083 -0
  98. data/opal/fron-ui/vendor/uuid.js +92 -0
  99. data/opal/fron_ui.rb +13 -0
  100. data/spec/behaviors/action_spec.rb +34 -0
  101. data/spec/behaviors/actions_spec.rb +38 -0
  102. data/spec/behaviors/confirmation_spec.rb +23 -0
  103. data/spec/behaviors/dropdown_spec.rb +32 -0
  104. data/spec/behaviors/render_spec.rb +20 -0
  105. data/spec/behaviors/rest_spec.rb +70 -0
  106. data/spec/behaviors/selectable_children_spec.rb +40 -0
  107. data/spec/behaviors/serialize_spec.rb +34 -0
  108. data/spec/components/action_spec.rb +7 -0
  109. data/spec/components/base_spec.rb +19 -0
  110. data/spec/components/box_spec.rb +7 -0
  111. data/spec/components/button_spec.rb +9 -0
  112. data/spec/components/calendar_spec.rb +58 -0
  113. data/spec/components/checkbox_spec.rb +20 -0
  114. data/spec/components/chooser_spec.rb +75 -0
  115. data/spec/components/color_panel_spec.rb +49 -0
  116. data/spec/components/color_picker_spec.rb +41 -0
  117. data/spec/components/container_spec.rb +23 -0
  118. data/spec/components/date_picker_spec.rb +71 -0
  119. data/spec/components/drag_spec.rb +20 -0
  120. data/spec/components/dropdown_spec.rb +33 -0
  121. data/spec/components/image_spec.rb +33 -0
  122. data/spec/components/input_spec.rb +8 -0
  123. data/spec/components/list_spec.rb +10 -0
  124. data/spec/components/loader_spec.rb +9 -0
  125. data/spec/components/notifications_spec.rb +17 -0
  126. data/spec/components/number_spec.rb +64 -0
  127. data/spec/components/progress_spec.rb +23 -0
  128. data/spec/components/slider_spec.rb +25 -0
  129. data/spec/components/tabs_spec.rb +50 -0
  130. data/spec/components/textarea_spec.rb +7 -0
  131. data/spec/components/time_spec.rb +37 -0
  132. data/spec/components/title_spec.rb +11 -0
  133. data/spec/examples/comments_spec.rb +72 -0
  134. data/spec/examples/todos_spec.rb +39 -0
  135. data/spec/lib/collection_spec.rb +38 -0
  136. data/spec/lib/lorem_spec.rb +55 -0
  137. data/spec/lib/state_serializer_spec.rb +58 -0
  138. data/spec/lib/storage_spec.rb +39 -0
  139. data/spec/spec_helper.rb +1 -0
  140. metadata +223 -0
@@ -0,0 +1,29 @@
1
+ module UI
2
+ # Simple Icon component
3
+ #
4
+ # @author Gusztáv Szikszai
5
+ # @since 0.1.0
6
+ class Icon < UI::Base
7
+ tag 'ui-icon'
8
+
9
+ style justifyContent: :center,
10
+ display: 'inline-flex',
11
+ alignItems: :center,
12
+ fontWeight: :normal,
13
+ '&:not([clickable])' => { pointerEvents: :none },
14
+ '&[clickable]' => { cursor: :pointer,
15
+ '&:hover' => { color: -> { colors.focus } } }
16
+
17
+ # Sets the glyph
18
+ #
19
+ # @param value [String] The glyph
20
+ def glyph=(value)
21
+ self[:glyph] = value
22
+ self[:class] = "ion-#{value}"
23
+ end
24
+
25
+ def glyph
26
+ self[:glyph]
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,77 @@
1
+ require 'fron-ui/components/loader'
2
+
3
+ module UI
4
+ # Component for displaying an image, with
5
+ # a transition after it loads.
6
+ #
7
+ # @author Gusztáv Szikszai
8
+ # @since 0.1.0
9
+ class Image < Fron::Component
10
+ tag 'ui-image'
11
+
12
+ component :img, :img
13
+ component :loader, UI::Loader
14
+
15
+ style borderRadius: -> { (theme.border_radius * 2).em },
16
+ background: -> { dampen colors.background, 0.05 },
17
+ display: 'inline-block',
18
+ position: :relative,
19
+ 'ui-loader' => { color: -> { dampen colors.background, 0.2 },
20
+ position: :absolute,
21
+ bottom: 0,
22
+ right: 0,
23
+ left: 0,
24
+ top: 0 },
25
+ img: { transition: 'opacity 320ms',
26
+ borderRadius: :inherit,
27
+ height: :inherit,
28
+ width: :inherit,
29
+ opacity: 0,
30
+ '&.loaded' => { opacity: 1 } }
31
+
32
+ # Initializes the component
33
+ # and listens on the load event
34
+ # because it doesn't bubble.
35
+ def initialize
36
+ super
37
+ @img.on(:load) { loaded }
38
+ end
39
+
40
+ # Adds the loaded class
41
+ def loaded
42
+ @img.add_class :loaded
43
+ @loader.loading = false
44
+ end
45
+
46
+ # Sets the width of the image
47
+ #
48
+ # @param value [Numeric] The width
49
+ def width=(value)
50
+ @style.width = value
51
+ end
52
+
53
+ # Sets the height of the image
54
+ #
55
+ # @param value [Numeric] The height
56
+ def height=(value)
57
+ @style.height = value
58
+ end
59
+
60
+ # Returns the src attribute of the image
61
+ #
62
+ # @return [String] The attribute
63
+ def src
64
+ @img[:src]
65
+ end
66
+
67
+ # Sets the src of the image
68
+ #
69
+ # @param value [String] The URL
70
+ def src=(value)
71
+ return if !value || @img[:src] == value
72
+ @img.remove_class :loaded
73
+ @loader.loading = true
74
+ timeout(320) { @img[:src] = value }
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,30 @@
1
+ module UI
2
+ # Input component, basically the input element wrapped
3
+ # and styled.
4
+ #
5
+ # @author Gusztáv Szikszai
6
+ # @since 0.1.0
7
+ class Input < Base
8
+ tag 'input'
9
+
10
+ defaults type: 'text'
11
+
12
+ attribute_accessor :placeholder
13
+ attribute_accessor :readonly, default: false
14
+
15
+ style borderRadius: -> { theme.border_radius.em },
16
+ color: -> { readable_color(colors.input) },
17
+ padding: -> { "0 #{theme.spacing.em}" },
18
+ fontFamily: -> { theme.font_family },
19
+ lineHeight: -> { theme.size.em },
20
+ background: -> { colors.input },
21
+ height: -> { theme.size.em },
22
+ fontSize: :inherit,
23
+ border: 0,
24
+ '&:focus' => {
25
+ boxShadow: -> { theme.focus_box_shadow.call },
26
+ borderColor: :transparent,
27
+ outline: :none
28
+ }
29
+ end
30
+ end
@@ -0,0 +1,9 @@
1
+ module UI
2
+ # Simple label component
3
+ #
4
+ # @author Gusztáv Szikszai
5
+ # @since 0.1.0
6
+ class Label < UI::Base
7
+ tag 'ui-label'
8
+ end
9
+ end
@@ -0,0 +1,34 @@
1
+ module UI
2
+ # List component
3
+ #
4
+ # Features:
5
+ # * Empty message display in an :after element
6
+ # * Striped backgrounds for items
7
+ # * Overflow auto
8
+ #
9
+ # @author Gusztáv Szikszai
10
+ # @since 0.1.0
11
+ class List < Collection
12
+ tag 'ui-list'
13
+
14
+ style overflow: :auto,
15
+ display: :block,
16
+ '> *' => { display: :block,
17
+ '& + *' => { borderTop: -> { "1px solid #{dampen colors.background, 0.025}" } } },
18
+ '&:empty' => { padding: -> { theme.spacing.em },
19
+ justifyContent: :center,
20
+ alignItems: :center,
21
+ textAlign: :center,
22
+ display: :flex },
23
+ '&:empty:after' => { content: 'attr(empty_message)',
24
+ fontSize: 2.em,
25
+ opacity: 0.25 }
26
+
27
+ # Sets the flex value
28
+ #
29
+ # @param value [Numeric] The value
30
+ def flex=(value)
31
+ @style.flex = value
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,63 @@
1
+ # rubocop:disable DoubleNegation
2
+
3
+ module UI
4
+ # Loader component
5
+ #
6
+ # @author Gusztáv Szikszai
7
+ # @since 0.1.0
8
+ class Loader < Base
9
+ tag 'ui-loader'
10
+
11
+ component :div, 'ui-loader-div'
12
+
13
+ keyframes 'ui-loader', '0%' => { transform: 'rotate(0deg)' },
14
+ '50%' => { transform: 'rotate(179.9deg)' },
15
+ '100%' => { transform: 'rotate(359.9deg)' }
16
+
17
+ style transition: 'opacity 320ms',
18
+ justifyContent: :center,
19
+ alignItems: :center,
20
+ minHeight: 2.em,
21
+ minWidth: 2.em,
22
+ display: :flex,
23
+ color: -> { colors.primary },
24
+ opacity: 0,
25
+ pointerEvents: :none,
26
+ '&.loading' => {
27
+ opacity: 1
28
+ },
29
+ 'ui-loader-div' => {
30
+ animation: 'ui-loader 1.2s infinite linear',
31
+ border: '0.15em solid currentColor',
32
+ borderTop: '0.15em solid transparent',
33
+ borderBottom: '0.15em solid transparent',
34
+ display: :flex,
35
+ justifyContent: :center,
36
+ alignItems: :center,
37
+ borderRadius: '50%',
38
+ height: 2.em,
39
+ width: 2.em,
40
+ '&:before' => {
41
+ content: '""',
42
+ border: '0.15em solid currentColor',
43
+ borderRadius: '50%',
44
+ height: 1.em,
45
+ width: 1.em
46
+ }
47
+ }
48
+
49
+ # Sets the loading flag
50
+ #
51
+ # @param value [Boolean] The value
52
+ def loading=(value)
53
+ toggle_class :loading, !!value
54
+ end
55
+
56
+ # Returns the loading flag
57
+ #
58
+ # @return [Boolean] The value
59
+ def loading
60
+ has_class(:loading)
61
+ end
62
+ end
63
+ end
File without changes
@@ -0,0 +1,73 @@
1
+ module UI
2
+ # Component for displaying notifications.
3
+ #
4
+ # @author Gusztáv Szikszai
5
+ # @since 0.1.0
6
+ class Notifications < Base
7
+ # Notification component-
8
+ #
9
+ # @author Gusztáv Szikszai
10
+ # @since 0.1.0
11
+ class Notification < Base
12
+ include UI::Behaviors::Transition
13
+
14
+ tag 'ui-notification'
15
+
16
+ style background: -> { rgba colors.primary, 0.85 },
17
+ borderRadius: -> { theme.border_radius.em },
18
+ color: -> { readable_color colors.primary },
19
+ fontSize: 1.2.em,
20
+ fontWeight: 600,
21
+ display: :block,
22
+ lineHeight: 1,
23
+ span: {
24
+ display: :block,
25
+ padding: -> { theme.spacing.em },
26
+ paddingBottom: -> { (theme.spacing * 1.2).em }
27
+ }
28
+
29
+ component :span, :span
30
+
31
+ transition :show, duration: '500ms',
32
+ frames: { '0%' => { opacity: 0 },
33
+ '100%' => { opacity: 1 } },
34
+ callback: :hide
35
+
36
+ transition :hide, duration: '500ms',
37
+ delay: '3s',
38
+ frames: { '0%' => { opacity: 1 },
39
+ '100%' => { opacity: 0 } },
40
+ callback: :remove!
41
+
42
+ # Initializes the component, starting
43
+ # the show transition.
44
+ def initialize
45
+ super
46
+ transition! :show
47
+ end
48
+
49
+ # Hides the component with the hide transition.
50
+ def hide
51
+ transition! :hide
52
+ end
53
+ end
54
+
55
+ tag 'ui-notifications'
56
+
57
+ style position: :absolute,
58
+ bottom: 1.5.em,
59
+ left: 1.5.em,
60
+ '> * + *' => { marginTop: -> { (theme.spacing / 1.5).em } }
61
+
62
+ # Pushes a new notification with the given
63
+ # message into the queue.
64
+ #
65
+ # @param message [String] The message
66
+ def push(message)
67
+ noti = Notification.new
68
+ noti.span.text = message
69
+ noti >> self
70
+ noti
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,202 @@
1
+ require 'fron/utils/drag'
2
+
3
+ module UI
4
+ # Range input element. This element is editable just like a normal
5
+ # input element can, the difference is that this element is draggable.
6
+ # When dragging the value is incremeted or decremented depending on the
7
+ # direction of the drag. The element can be limited to an upper and a lower value.
8
+ #
9
+ # @attr_reader drag [Fron::Drag] The drag instance
10
+ # @attr affix [String] The affix (px, %, em, ...)
11
+ # @attr label [String] The label to be displayed
12
+ # @attr step [Float] The step modifier to apply to the step, default to 1
13
+ # @attr min [Float] The minimal possible value, defaults to -infinity
14
+ # @attr max [Float] The maximum possible value, defaults to infinity
15
+ # @attr round [Float] The rounding value, defaults to 2
16
+ #
17
+ # @author Gusztáv Szikszai
18
+ # @since 0.1.0
19
+ class NumberRange < Base
20
+ # Input component
21
+ class Input < Fron::Component
22
+ tag 'ui-number-range-input'
23
+
24
+ attribute_accessor :label
25
+ attribute_accessor :affix
26
+
27
+ style borderRadius: -> { theme.border_radius.em },
28
+ lineHeight: -> { theme.size.em },
29
+ background: -> { colors.input },
30
+ height: -> { theme.size.em },
31
+ textAlign: :center,
32
+ display: :block,
33
+ fontWeight: 600,
34
+ '&:before' => { content: 'attr(label)',
35
+ marginRight: 0.2.em,
36
+ fontWeight: :normal },
37
+ '&:after' => { content: 'attr(affix)' },
38
+ '&:focus' => { boxShadow: -> { theme.focus_box_shadow.call },
39
+ outline: :none }
40
+ end
41
+
42
+ extend Forwardable
43
+
44
+ attr_reader :drag
45
+
46
+ tag 'ui-number-range'
47
+
48
+ component :input, Input, contenteditable: true
49
+
50
+ def_delegators :@input, :affix=, :affix, :label=, :label
51
+
52
+ on :keydown, :keydown
53
+ on :input, :input
54
+ on :mousemove, :on_mouse_move
55
+ on :mousedown, :on_mouse_down
56
+
57
+ attribute_accessor :step, default: 1, coerce: :to_f
58
+ attribute_accessor :round, default: 1, coerce: :to_f
59
+ attribute_accessor :max, default: Float::INFINITY, coerce: :to_f
60
+ attribute_accessor :min, default: -Float::INFINITY, coerce: :to_f
61
+
62
+ style color: -> { readable_color(colors.input) },
63
+ minWidth: -> { (theme.size * 5).em },
64
+ display: 'inline-block',
65
+ position: :relative,
66
+ '&:after, &:before' => { borderStyle: :solid,
67
+ position: :absolute,
68
+ marginTop: -0.3.em,
69
+ content: "''",
70
+ opacity: 0.5,
71
+ top: '50%',
72
+ height: 0,
73
+ width: 0 },
74
+ '&:after' => { borderColor: 'transparent currentColor transparent transparent',
75
+ borderWidth: '0.35em 0.4em 0.35em 0',
76
+ left: 0.75.em },
77
+ '&:before' => { borderColor: 'transparent transparent transparent currentColor',
78
+ borderWidth: '0.35em 0 0.35em 0.4em',
79
+ right: 0.75.em }
80
+
81
+ # Creates a new instance
82
+ def initialize
83
+ super
84
+ @input.on(:blur) { blur }
85
+ self.value = 0
86
+ setup_drag
87
+ end
88
+
89
+ def _attribute_changed
90
+ reset_value
91
+ end
92
+
93
+ # Returns the value of the field
94
+ #
95
+ # @return [Float] The value of the field
96
+ def value
97
+ @value.to_f
98
+ end
99
+
100
+ def _value(value)
101
+ value = value.to_f.clamp(min, max)
102
+ return if @value == value
103
+ @value = value
104
+ end
105
+
106
+ # Sets the value of the field
107
+ #
108
+ # @param value [Float] The value
109
+ def value=(value)
110
+ _value value
111
+ @input.text = format "%.#{round}f", @value
112
+ trigger 'change'
113
+ end
114
+
115
+ private
116
+
117
+ # Resets the value when attribute changes
118
+ def reset_value
119
+ self.value = value
120
+ end
121
+
122
+ # Sets up dragging.
123
+ def setup_drag
124
+ @drag = Fron::Drag.new self, 0
125
+
126
+ @drag.on('start') { @start_value = value }
127
+ @drag.on('move') { on_drag_move }
128
+ @drag.on('end') { on_drag_end }
129
+ end
130
+
131
+ # Runs when drag end
132
+ def on_drag_end
133
+ DOM::Document.body.style.cursor = ''
134
+ blur
135
+ end
136
+
137
+ # Runs when drag moves
138
+ def on_drag_move
139
+ DOM::Document.body.style.cursor = 'move'
140
+ value = (@start_value - @drag.diff.x * step).round(round)
141
+ self.value = value if @value != value
142
+ end
143
+
144
+ # Runs when input changes. It sets the value if the emelement
145
+ # is not empty, otherwise it inserts a non-width space to prevent
146
+ # caret jumping in chrome.
147
+ def input
148
+ @input.html = '&#xfeff;' if text.strip == ''
149
+ _value @input.html
150
+ end
151
+
152
+ # Runs when key is pressed. Prevents hitting the enter key.
153
+ #
154
+ # :reek:FeatureEnvy
155
+ #
156
+ # @param event [Event] The event
157
+ def keydown(event)
158
+ return unless event.key == :enter
159
+ event.prevent_default
160
+ @input.blur
161
+ end
162
+
163
+ # Runs when the element is blurred. Sets the value form
164
+ # the elements text.
165
+ def blur
166
+ self.value = text
167
+ end
168
+
169
+ # Runs on pointer move. Sets the cursor to move when not
170
+ # in the center of the element
171
+ #
172
+ # @param event [Event] The event
173
+ def on_mouse_move(event)
174
+ @style.cursor = in_select_region?(event.page_x) ? '' : 'move'
175
+ end
176
+
177
+ # Runs on pointer down. Prevents propagation so dragging
178
+ # cannot start.
179
+ #
180
+ # :reek:FeatureEnvy
181
+ #
182
+ # @param event [Event] The event
183
+ def on_mouse_down(event)
184
+ @input.focus
185
+ if in_select_region?(event.page_x)
186
+ event.stop_immediate_propagation
187
+ else
188
+ event.prevent_default
189
+ end
190
+ end
191
+
192
+ # Returns form to position if it is in the region that
193
+ # allow selection.
194
+ #
195
+ # @param position [type] The position (horizontal) to be checked
196
+ #
197
+ # @return [Boolean] True if the position is in the region otherwise false.
198
+ def in_select_region?(position)
199
+ (left + width / 2 - position).abs <= width / 4.5
200
+ end
201
+ end
202
+ end