You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@royale.apache.org by ca...@apache.org on 2018/08/24 19:35:10 UTC
[royale-asjs] branch develop updated: Jewel NumericStepper first
round
This is an automated email from the ASF dual-hosted git repository.
carlosrovira pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/royale-asjs.git
The following commit(s) were added to refs/heads/develop by this push:
new 49926ad Jewel NumericStepper first round
49926ad is described below
commit 49926add111921696e7fb14d8772add304f53c74
Author: Carlos Rovira <ca...@apache.org>
AuthorDate: Fri Aug 24 21:35:04 2018 +0200
Jewel NumericStepper first round
---
.../src/main/royale/ButtonPlayGround.mxml | 2 +
.../projects/Jewel/src/main/resources/defaults.css | 24 ++
.../Jewel/src/main/resources/jewel-manifest.xml | 2 +
.../projects/Jewel/src/main/royale/JewelClasses.as | 3 +
.../main/royale/org/apache/royale/jewel/Button.as | 2 +-
.../org/apache/royale/jewel/NumericStepper.as | 192 ++++++++++++++++
.../main/royale/org/apache/royale/jewel/Spinner.as | 182 ++++++++++++++++
.../beads/controllers/SpinnerMouseController.as | 131 +++++++++++
.../jewel/beads/controls/spinner/ISpinnerView.as | 69 ++++++
.../royale/jewel/beads/views/NumericStepperView.as | 242 +++++++++++++++++++++
.../apache/royale/jewel/beads/views/SpinnerView.as | 212 ++++++++++++++++++
.../src/main/sass/components/_numericstepper.sass | 59 +++++
.../projects/Jewel/src/main/sass/defaults.sass | 1 +
.../JewelTheme/src/main/resources/defaults.css | 28 +++
.../sass/components-primary/_numericstepper.sass | 61 ++++++
.../themes/JewelTheme/src/main/sass/defaults.sass | 1 +
16 files changed, 1210 insertions(+), 1 deletion(-)
diff --git a/examples/royale/JewelExample/src/main/royale/ButtonPlayGround.mxml b/examples/royale/JewelExample/src/main/royale/ButtonPlayGround.mxml
index e99c23e..e1eeb42 100644
--- a/examples/royale/JewelExample/src/main/royale/ButtonPlayGround.mxml
+++ b/examples/royale/JewelExample/src/main/royale/ButtonPlayGround.mxml
@@ -97,6 +97,8 @@ limitations under the License.
<js:FontIcon text="{MaterialIconType.FACE}" material="true"/>
</j:icon>
</j:IconButton>
+
+ <j:NumericStepper/>
</j:Card>
</j:GridCell>
</j:Grid>
diff --git a/frameworks/projects/Jewel/src/main/resources/defaults.css b/frameworks/projects/Jewel/src/main/resources/defaults.css
index 77e4ec2..20bf8c3 100644
--- a/frameworks/projects/Jewel/src/main/resources/defaults.css
+++ b/frameworks/projects/Jewel/src/main/resources/defaults.css
@@ -2732,6 +2732,30 @@ j|Navigation {
IContentView: ClassReference("org.apache.royale.html.supportClasses.DataGroup");
}
}
+.jewel.numericstepper .jewel.textinput {
+ display: inline-flex;
+}
+
+j|NumericStepper {
+ IBeadModel: ClassReference("org.apache.royale.jewel.beads.models.RangeModel");
+ IBeadView: ClassReference("org.apache.royale.jewel.beads.views.NumericStepperView");
+}
+
+.jewel.spinner {
+ display: inline-flex;
+ flex-direction: column;
+ vertical-align: middle;
+}
+.jewel.spinner .jewel.button {
+ display: flex;
+}
+
+j|Spinner {
+ IBeadModel: ClassReference("org.apache.royale.jewel.beads.models.RangeModel");
+ IBeadView: ClassReference("org.apache.royale.jewel.beads.views.SpinnerView");
+ IBeadController: ClassReference("org.apache.royale.jewel.beads.controllers.SpinnerMouseController");
+}
+
.jewel.radiobutton {
display: inline-flex;
position: relative;
diff --git a/frameworks/projects/Jewel/src/main/resources/jewel-manifest.xml b/frameworks/projects/Jewel/src/main/resources/jewel-manifest.xml
index 471cd89..bffb938 100644
--- a/frameworks/projects/Jewel/src/main/resources/jewel-manifest.xml
+++ b/frameworks/projects/Jewel/src/main/resources/jewel-manifest.xml
@@ -47,6 +47,8 @@
<component id="TextInput" class="org.apache.royale.jewel.TextInput"/>
<component id="IconTextInput" class="org.apache.royale.jewel.IconTextInput"/>
<component id="TextArea" class="org.apache.royale.jewel.TextArea"/>
+ <component id="Spinner" class="org.apache.royale.jewel.Spinner" />
+ <component id="NumericStepper" class="org.apache.royale.jewel.NumericStepper" />
<component id="Slider" class="org.apache.royale.jewel.Slider"/>
<component id="RadioButton" class="org.apache.royale.jewel.RadioButton"/>
<component id="CheckBox" class="org.apache.royale.jewel.CheckBox"/>
diff --git a/frameworks/projects/Jewel/src/main/royale/JewelClasses.as b/frameworks/projects/Jewel/src/main/royale/JewelClasses.as
index d9882ce..2425926 100644
--- a/frameworks/projects/Jewel/src/main/royale/JewelClasses.as
+++ b/frameworks/projects/Jewel/src/main/royale/JewelClasses.as
@@ -36,6 +36,7 @@ package
import org.apache.royale.jewel.beads.models.DateChooserModel; DateChooserModel;
import org.apache.royale.jewel.beads.models.DataProviderModel; DataProviderModel;
+ import org.apache.royale.jewel.beads.controllers.SpinnerMouseController; SpinnerMouseController;
import org.apache.royale.jewel.beads.controllers.SliderMouseController; SliderMouseController;
import org.apache.royale.jewel.beads.controllers.DateChooserMouseController; DateChooserMouseController;
import org.apache.royale.jewel.beads.controllers.DateFieldMouseController; DateFieldMouseController;
@@ -45,6 +46,8 @@ package
import org.apache.royale.jewel.beads.controllers.TableCellSelectionMouseController; TableCellSelectionMouseController;
import org.apache.royale.jewel.beads.views.ImageView; ImageView;
+ import org.apache.royale.jewel.beads.views.SpinnerView; SpinnerView;
+ import org.apache.royale.jewel.beads.views.NumericStepperView; NumericStepperView;
import org.apache.royale.jewel.beads.views.SliderView; SliderView;
import org.apache.royale.jewel.beads.views.AlertView; AlertView;
import org.apache.royale.jewel.beads.views.TitleBarView; TitleBarView;
diff --git a/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/Button.as b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/Button.as
index fb59004..1d8a676 100644
--- a/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/Button.as
+++ b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/Button.as
@@ -452,7 +452,7 @@ package org.apache.royale.jewel
*/
override protected function createElement():WrappedHTMLElement
{
- addElementToWrapper(this,'button');
+ addElementToWrapper(this, 'button');
element.setAttribute('type', 'button');
/* AJH comment out until we figure out why it is needed
if (org.apache.royale.core.ValuesManager.valuesImpl.getValue) {
diff --git a/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/NumericStepper.as b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/NumericStepper.as
new file mode 100644
index 0000000..f88f2c6
--- /dev/null
+++ b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/NumericStepper.as
@@ -0,0 +1,192 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package org.apache.royale.jewel
+{
+ import org.apache.royale.core.IRangeModel;
+ import org.apache.royale.core.StyledUIBase;
+ COMPILE::JS
+ {
+ import goog.events;
+ import org.apache.royale.core.IBead;
+ import org.apache.royale.core.WrappedHTMLElement;
+ import org.apache.royale.events.IEventDispatcher;
+ import org.apache.royale.html.util.addElementToWrapper;
+ }
+
+ [Event(name="valueChange", type="org.apache.royale.events.Event")]
+
+ /**
+ * The NumericStepper class is a component that displays a numeric
+ * value and up/down controls (using a org.apache.royale.jewel.Spinner) to
+ * increase and decrease the value by specific amounts. The NumericStepper uses the following beads:
+ *
+ * org.apache.royale.core.IBeadModel: the data model for the component of type org.apache.royale.core.IRangeModel.
+ * org.apache.royale.core.IBeadView: constructs the parts of the component.
+ * org.apache.royale.core.IBeadController: handles the input events.
+ *
+ * @toplevel
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.9.3
+ */
+ public class NumericStepper extends StyledUIBase
+ {
+ /**
+ * constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.9.3
+ */
+ public function NumericStepper()
+ {
+ super();
+ typeNames = 'jewel numericstepper';
+ }
+
+ [Bindable("valueChange")]
+ /**
+ * The current value of the control.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.9.3
+ * @royaleignorecoercion org.apache.royale.core.IRangeModel
+ */
+ public function get value():Number
+ {
+ return IRangeModel(model).value;
+ }
+ /**
+ * @royaleignorecoercion org.apache.royale.core.IRangeModel
+ */
+ public function set value(newValue:Number):void
+ {
+ IRangeModel(model).value = newValue;
+ }
+
+ /**
+ * The minimum value the control will display.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.9.3
+ * @royaleignorecoercion org.apache.royale.core.IRangeModel
+ */
+ public function get minimum():Number
+ {
+ return IRangeModel(model).minimum;
+ }
+ /**
+ * @royaleignorecoercion org.apache.royale.core.IRangeModel
+ */
+ public function set minimum(value:Number):void
+ {
+ IRangeModel(model).minimum = value;
+ }
+
+ /**
+ * The maximum value the control will display.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.9.3
+ * @royaleignorecoercion org.apache.royale.core.IRangeModel
+ */
+ public function get maximum():Number
+ {
+ return IRangeModel(model).maximum;
+ }
+ /**
+ * @royaleignorecoercion org.apache.royale.core.IRangeModel
+ */
+ public function set maximum(value:Number):void
+ {
+ IRangeModel(model).maximum = value;
+ }
+
+ /**
+ * The amount to increase or descrease the value. The value
+ * will not exceed the minimum or maximum value. The final
+ * value is affected by the snapInterval.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.9.3
+ * @royaleignorecoercion org.apache.royale.core.IRangeModel
+ */
+ public function get stepSize():Number
+ {
+ return IRangeModel(model).stepSize;
+ }
+ /**
+ * @royaleignorecoercion org.apache.royale.core.IRangeModel
+ */
+ public function set stepSize(value:Number):void
+ {
+ IRangeModel(model).stepSize = value;
+ }
+
+ /**
+ * The modulus for the value. If this property is set,
+ * the value displayed with a muliple of the snapInterval.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.9.3
+ * @royaleignorecoercion org.apache.royale.core.IRangeModel
+ */
+ public function get snapInterval():Number
+ {
+ return IRangeModel(model).snapInterval;
+ }
+ /**
+ * @royaleignorecoercion org.apache.royale.core.IRangeModel
+ */
+ public function set snapInterval(value:Number):void
+ {
+ IRangeModel(model).snapInterval = value;
+ }
+
+ COMPILE::JS
+ private var input:TextInput;
+
+ COMPILE::JS
+ private var spinner:Spinner;
+
+ /**
+ * @royaleignorecoercion org.apache.royale.core.WrappedHTMLElement
+ */
+ COMPILE::JS
+ override protected function createElement():WrappedHTMLElement
+ {
+ addElementToWrapper(this, 'div');
+ positioner = element;
+ return element;
+ }
+
+ }
+}
diff --git a/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/Spinner.as b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/Spinner.as
new file mode 100644
index 0000000..93857ad
--- /dev/null
+++ b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/Spinner.as
@@ -0,0 +1,182 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package org.apache.royale.jewel
+{
+ import org.apache.royale.core.IRangeModel;
+ import org.apache.royale.core.StyledUIBase;
+
+ COMPILE::JS
+ {
+ import org.apache.royale.core.WrappedHTMLElement;
+ import org.apache.royale.html.util.addElementToWrapper;
+ }
+
+ [Event(name="valueChange", type="org.apache.royale.events.Event")]
+
+ /**
+ * The Spinner class is a component that displays a control for incrementing a value
+ * and a control for decrementing a value. The org.apache.royale.jewel.NumericStepper
+ * uses a Spinner as part of the component. Spinner uses the following beads:
+ *
+ * org.apache.royale.core.IBeadModel: an IRangeModel to hold the properties.
+ * org.apache.royale.core.IBeadView: the bead that constructs the visual parts of the Spinner.
+ * org.apache.royale.core.IBeadController: a bead that handles the input events.
+ *
+ * @toplevel
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.9.3
+ */
+ public class Spinner extends StyledUIBase
+ {
+ /**
+ * constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.9.3
+ */
+ public function Spinner()
+ {
+ super();
+ typeNames = "jewel spinner";
+ }
+
+ /**
+ * The current value of the Spinner.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.9.3
+ * @royaleignorecoercion org.apache.royale.core.IRangeModel
+ */
+ public function get value():Number
+ {
+ return IRangeModel(model).value;
+ }
+ /**
+ * @royaleignorecoercion org.apache.royale.core.IRangeModel
+ */
+ public function set value(newValue:Number):void
+ {
+ IRangeModel(model).value = newValue;
+ }
+
+ /**
+ * The minimum value of the Spinner.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.9.3
+ * @royaleignorecoercion org.apache.royale.core.IRangeModel
+ */
+ public function get minimum():Number
+ {
+ return IRangeModel(model).minimum;
+ }
+ /**
+ * @royaleignorecoercion org.apache.royale.core.IRangeModel
+ */
+ public function set minimum(value:Number):void
+ {
+ IRangeModel(model).minimum = value;
+ }
+
+ /**
+ * The maximum value of the Spinner.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.9.3
+ * @royaleignorecoercion org.apache.royale.core.IRangeModel
+ */
+ public function get maximum():Number
+ {
+ return IRangeModel(model).maximum;
+ }
+ /**
+ * @royaleignorecoercion org.apache.royale.core.IRangeModel
+ */
+ public function set maximum(value:Number):void
+ {
+ IRangeModel(model).maximum = value;
+ }
+
+ /**
+ * The modulus for the value. If this property is set,
+ * the value displayed with a muliple of the snapInterval.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.9.3
+ * @royaleignorecoercion org.apache.royale.core.IRangeModel
+ */
+ public function get snapInterval():Number
+ {
+ return IRangeModel(model).snapInterval;
+ }
+ /**
+ * @royaleignorecoercion org.apache.royale.core.IRangeModel
+ */
+ public function set snapInterval(value:Number):void
+ {
+ IRangeModel(model).snapInterval = value;
+ }
+
+ /**
+ * The amount to increase or descrease the value. The value
+ * will not exceed the minimum or maximum value. The final
+ * value is affected by the snapInterval.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.9.3
+ * @royaleignorecoercion org.apache.royale.core.IRangeModel
+ */
+ public function get stepSize():Number
+ {
+ return IRangeModel(model).stepSize;
+ }
+ /**
+ * @royaleignorecoercion org.apache.royale.core.IRangeModel
+ */
+ public function set stepSize(value:Number):void
+ {
+ IRangeModel(model).stepSize = value;
+ }
+
+ /**
+ * @royaleignorecoercion org.apache.royale.core.WrappedHTMLElement
+ */
+ COMPILE::JS
+ override protected function createElement():WrappedHTMLElement
+ {
+ addElementToWrapper(this,'div');
+ positioner = element;
+ return element;
+ }
+ }
+}
diff --git a/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/controllers/SpinnerMouseController.as b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/controllers/SpinnerMouseController.as
new file mode 100644
index 0000000..a7aa24f
--- /dev/null
+++ b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/controllers/SpinnerMouseController.as
@@ -0,0 +1,131 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package org.apache.royale.jewel.beads.controllers
+{
+ import org.apache.royale.core.IBeadController;
+ import org.apache.royale.core.IRangeModel;
+ import org.apache.royale.core.IStrand;
+ import org.apache.royale.core.UIBase;
+ import org.apache.royale.events.IEventDispatcher;
+ import org.apache.royale.events.MouseEvent;
+ import org.apache.royale.events.ValueChangeEvent;
+ import org.apache.royale.jewel.beads.controls.spinner.ISpinnerView;
+ COMPILE::JS
+ {
+ import org.apache.royale.jewel.Spinner;
+ import org.apache.royale.jewel.Button;
+ import goog.events;
+ import goog.events.EventType;
+ }
+
+ /**
+ * The SpinnerMouseController class bead handles mouse events on the
+ * org.apache.royale.jewel.Spinner's component buttons, changing the
+ * value of the Spinner.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.9.3
+ */
+ public class SpinnerMouseController implements IBeadController
+ {
+ /**
+ * constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.9.3
+ */
+ public function SpinnerMouseController()
+ {
+ }
+
+ private var rangeModel:IRangeModel;
+
+ private var _strand:IStrand;
+
+ /**
+ * @copy org.apache.royale.core.IBead#strand
+ *
+ * @royaleignorecoercion org.apache.royale.jewel.Spinner
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.9.3
+ * @royaleignorecoercion org.apache.royale.jewel.beads.controls.spinner.ISpinnerView
+ * @royaleignorecoercion org.apache.royale.core.UIBase
+ * @royaleignorecoercion org.apache.royale.core.IRangeModel
+ */
+ public function set strand(value:IStrand):void
+ {
+ _strand = value;
+
+ rangeModel = UIBase(value).model as IRangeModel;
+
+ COMPILE::SWF
+ {
+ var spinnerBead:ISpinnerView = value.getBeadByType(ISpinnerView) as ISpinnerView;
+ spinnerBead.decrement.addEventListener(MouseEvent.CLICK, decrementClickHandler);
+ spinnerBead.decrement.addEventListener("buttonRepeat", decrementClickHandler);
+ spinnerBead.increment.addEventListener(MouseEvent.CLICK, incrementClickHandler);
+ spinnerBead.increment.addEventListener("buttonRepeat", incrementClickHandler);
+ }
+
+ COMPILE::JS
+ {
+ var spinnerBead:ISpinnerView = value.getBeadByType(ISpinnerView) as ISpinnerView;
+
+ var incrementButton:Button = spinnerBead.increment;
+ var decrementButton:Button = spinnerBead.decrement;
+
+ goog.events.listen(incrementButton.element, goog.events.EventType.CLICK,
+ incrementClickHandler);
+
+ goog.events.listen(decrementButton.element, goog.events.EventType.CLICK,
+ decrementClickHandler);
+ }
+ }
+
+ /**
+ * @private
+ * @royaleignorecoercion org.apache.royale.events.IEventDispatcher
+ */
+ private function decrementClickHandler( event:org.apache.royale.events.MouseEvent ) : void
+ {
+ var oldValue:Number = rangeModel.value;
+ rangeModel.value = Math.max(rangeModel.minimum, rangeModel.value - rangeModel.stepSize);
+ var vce:ValueChangeEvent = ValueChangeEvent.createUpdateEvent(_strand, "value", oldValue, rangeModel.value);
+ IEventDispatcher(_strand).dispatchEvent(vce);
+ }
+
+ /**
+ * @private
+ * @royaleignorecoercion org.apache.royale.events.IEventDispatcher
+ */
+ private function incrementClickHandler( event:org.apache.royale.events.MouseEvent ) : void
+ {
+ var oldValue:Number = rangeModel.value;
+ rangeModel.value = Math.min(rangeModel.maximum, rangeModel.value + rangeModel.stepSize);
+ var vce:ValueChangeEvent = ValueChangeEvent.createUpdateEvent(_strand, "value", oldValue, rangeModel.value);
+ IEventDispatcher(_strand).dispatchEvent(vce);
+ }
+ }
+}
diff --git a/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/controls/spinner/ISpinnerView.as b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/controls/spinner/ISpinnerView.as
new file mode 100644
index 0000000..f6c2224
--- /dev/null
+++ b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/controls/spinner/ISpinnerView.as
@@ -0,0 +1,69 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package org.apache.royale.jewel.beads.controls.spinner
+{
+ COMPILE::SWF
+ {
+ import flash.display.DisplayObject;
+ }
+ COMPILE::JS
+ {
+ import org.apache.royale.jewel.Button;
+ }
+
+ import org.apache.royale.core.IBead;
+
+ /**
+ * The ISpinnerView interface provides the protocol for any bead that
+ * creates the visual parts for a org.apache.royale.jewel.Spinner control.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.9.3
+ */
+ public interface ISpinnerView extends IBead
+ {
+ /**
+ * The component used to increment the org.apache.royale.jewel.Spinner value.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.9.3
+ */
+ COMPILE::SWF
+ function get increment():DisplayObject;
+ COMPILE::JS
+ function get increment():Button;
+
+ /**
+ * The component used to decrement the org.apache.royale.jewel.Spinner value.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.9.3
+ */
+ COMPILE::SWF
+ function get decrement():DisplayObject;
+ COMPILE::JS
+ function get decrement():Button;
+ }
+}
diff --git a/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/views/NumericStepperView.as b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/views/NumericStepperView.as
new file mode 100644
index 0000000..24960ce
--- /dev/null
+++ b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/views/NumericStepperView.as
@@ -0,0 +1,242 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package org.apache.royale.jewel.beads.views
+{
+ import org.apache.royale.core.BeadViewBase;
+ import org.apache.royale.core.IBead;
+ import org.apache.royale.core.IBeadView;
+ import org.apache.royale.core.ILayoutChild;
+ import org.apache.royale.core.IParent;
+ import org.apache.royale.core.IParentIUIBase;
+ import org.apache.royale.core.IRangeModel;
+ import org.apache.royale.core.IStrand;
+ import org.apache.royale.core.IUIBase;
+ import org.apache.royale.core.UIBase;
+ import org.apache.royale.events.Event;
+ import org.apache.royale.events.ValueChangeEvent
+ import org.apache.royale.events.IEventDispatcher;
+ import org.apache.royale.jewel.Label;
+ import org.apache.royale.jewel.Spinner;
+ import org.apache.royale.jewel.TextInput;
+
+ /**
+ * The NumericStepperView class creates the visual elements of the
+ * org.apache.royale.jewel.NumericStepper component. A NumberStepper consists of a
+ * org.apache.royale.jewel.TextInput component to display the value and a
+ * org.apache.royale.jewel.Spinner to change the value.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.9.3
+ */
+ public class NumericStepperView extends BeadViewBase implements IBeadView
+ {
+ /**
+ * constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.9.3
+ */
+ public function NumericStepperView()
+ {
+ }
+
+ private var label:Label;
+ private var input:TextInput;
+ private var spinner:Spinner;
+
+ /**
+ * @copy org.apache.royale.core.IBead#strand
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.9.3
+ * @royaleignorecoercion org.apache.royale.core.UIBase
+ * @royaleignorecoercion org.apache.royale.core.IBead
+ * @royaleignorecoercion org.apache.royale.core.IParent
+ * @royaleignorecoercion org.apache.royale.events.IEventDispatcher
+ */
+ override public function set strand(value:IStrand):void
+ {
+ super.strand = value;
+
+ // add an input field
+ input = new TextInput();
+ // input.className = "NumericStepperInput";
+ // input.typeNames = "NumericStepperInput";
+ (value as IParent).addElement(input);
+ // COMPILE::JS
+ // {
+ // input.positioner.style.display = 'inline-block';
+ // input.positioner.style.width = '100px';
+ // }
+ // add a spinner
+ spinner = new Spinner();
+ spinner.addBead( (value as UIBase).model as IBead);
+ (value as IParent).addElement(spinner);
+ // delay this until the resize event in JS
+ COMPILE::SWF
+ {
+ spinner.height = input.height;
+ spinner.width = input.height/2;
+ }
+ // COMPILE::JS
+ // {
+ // spinner.positioner.style.display = 'inline-block';
+ // }
+
+ // listen for changes to the text input field which will reset the
+ // value. ideally, we should either set the input to accept only
+ // numeric values or, barring that, reject non-numeric entries. we
+ // cannot do that right now however.
+ input.addEventListener("change",inputChangeHandler);
+
+ // listen for change events on the spinner so the value can be updated as
+ // as resizing the component
+ spinner.addEventListener("valueChange",spinnerValueChanged);
+ IEventDispatcher(value).addEventListener("widthChanged",sizeChangeHandler);
+ IEventDispatcher(value).addEventListener("heightChanged",sizeChangeHandler);
+ IEventDispatcher(value).addEventListener("sizeChanged",sizeChangeHandler);
+
+ // listen for changes to the model itself and update the UI accordingly
+ IEventDispatcher(UIBase(value).model).addEventListener("valueChange",modelChangeHandler);
+ IEventDispatcher(UIBase(value).model).addEventListener("minimumChange",modelChangeHandler);
+ IEventDispatcher(UIBase(value).model).addEventListener("maximumChange",modelChangeHandler);
+ IEventDispatcher(UIBase(value).model).addEventListener("stepSizeChange",modelChangeHandler);
+ IEventDispatcher(UIBase(value).model).addEventListener("snapIntervalChange",modelChangeHandler);
+
+ input.text = String(spinner.value);
+
+ COMPILE::SWF
+ {
+ var host:ILayoutChild = ILayoutChild(value);
+
+ // Complete the setup if the height is sized to content or has been explicitly set
+ // and the width is sized to content or has been explicitly set
+ if ((host.isHeightSizedToContent() || !isNaN(host.explicitHeight)) &&
+ (host.isWidthSizedToContent() || !isNaN(host.explicitWidth)))
+ sizeChangeHandler(null);
+ }
+ COMPILE::JS
+ {
+ // always run size change since there are no size change events
+ sizeChangeHandler(null);
+ }
+
+ }
+
+ /**
+ * @private
+ * @royaleignorecoercion org.apache.royale.core.UIBase
+ */
+ private function sizeChangeHandler(event:Event) : void
+ {
+ // first reads
+ var widthToContent:Boolean = (_strand as UIBase).isWidthSizedToContent();
+ var inputWidth:Number = input.width;
+ var inputHeight:Number = input.height;
+ var strandWidth:Number;
+ if (!widthToContent)
+ {
+ strandWidth = (_strand as UIBase).width;
+ }
+ // COMPILE::JS
+ // {
+ // spinner.height = inputHeight;
+ // spinner.width = inputHeight/2;
+ // }
+
+ // input.x = 0;
+ // input.y = 0;
+ if (!widthToContent)
+ input.width = strandWidth - spinner.width - 2;
+
+ COMPILE::SWF
+ {
+ spinner.x = inputWidth;
+ spinner.y = 0;
+ }
+ }
+
+ /**
+ * @private
+ * @royaleignorecoercion org.apache.royale.events.IEventDispatcher
+ */
+ private function spinnerValueChanged(event:ValueChangeEvent) : void
+ {
+ input.text = "" + spinner.value;
+
+ var newEvent:ValueChangeEvent = ValueChangeEvent.createUpdateEvent(_strand, "value", event.oldValue, event.newValue);
+ IEventDispatcher(_strand).dispatchEvent(newEvent);
+ }
+
+ /**
+ * @private
+ */
+ private function inputChangeHandler(event:Event) : void
+ {
+ var newValue:Number = Number(input.text);
+
+ if( !isNaN(newValue) ) {
+ spinner.value = newValue;
+ }
+ else {
+ input.text = String(spinner.value);
+ }
+ }
+
+ /**
+ * @private
+ * @royaleignorecoercion org.apache.royale.core.UIBase
+ * @royaleignorecoercion org.apache.royale.core.IRangeModel
+ */
+ private function modelChangeHandler( event:Event ) : void
+ {
+ var n:Number = IRangeModel(UIBase(_strand).model).value;
+ input.text = String(IRangeModel(UIBase(_strand).model).value);
+ }
+
+ /**
+ * The area containing the TextInput and Spinner controls.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.9.3
+ * @royaleignorecoercion org.apache.royale.core.IParentIUIBase
+ */
+ public function get contentView():IParentIUIBase
+ {
+ return _strand as IParentIUIBase;
+ }
+
+ /**
+ * @private
+ * @royaleignorecoercion org.apache.royale.core.IUIBase
+ */
+ public function get resizableView():IUIBase
+ {
+ return _strand as IUIBase;
+ }
+ }
+}
diff --git a/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/views/SpinnerView.as b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/views/SpinnerView.as
new file mode 100644
index 0000000..5bd0669
--- /dev/null
+++ b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/views/SpinnerView.as
@@ -0,0 +1,212 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package org.apache.royale.jewel.beads.views
+{
+COMPILE::SWF {
+ import flash.display.DisplayObject;
+}
+
+ import org.apache.royale.core.BeadViewBase;
+ import org.apache.royale.core.IBeadModel;
+ import org.apache.royale.core.IBeadView;
+ import org.apache.royale.core.IRangeModel;
+ import org.apache.royale.core.IStrand;
+ import org.apache.royale.core.ILayoutChild;
+ import org.apache.royale.core.UIBase;
+ import org.apache.royale.events.Event;
+ import org.apache.royale.events.IEventDispatcher;
+ import org.apache.royale.jewel.Button;
+ // import org.apache.royale.jewel.beads.controllers.ButtonAutoRepeatController;
+ import org.apache.royale.jewel.beads.controls.spinner.ISpinnerView
+
+COMPILE::JS {
+ import org.apache.royale.jewel.beads.controllers.SpinnerMouseController;
+}
+
+ /**
+ * The SpinnerView class creates the visual elements of the org.apache.royale.jewel.Spinner
+ * component.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.9.3
+ */
+ public class SpinnerView extends BeadViewBase implements ISpinnerView, IBeadView
+ {
+ /**
+ * constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.9.3
+ */
+ public function SpinnerView()
+ {
+ }
+
+ private var rangeModel:IRangeModel;
+
+ COMPILE::JS {
+ public var _increment:Button;
+ public var _decrement:Button;
+ private var controller:SpinnerMouseController;
+ }
+
+ COMPILE::SWF {
+ private var _decrement:DisplayObject;
+ private var _increment:DisplayObject;
+ }
+
+ /**
+ * @copy org.apache.royale.core.IBead#strand
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.9.3
+ * @royaleignorecoercion org.apache.royale.core.UIBase
+ * @royaleignorecoercion org.apache.royale.events.IEventDispatcher
+ */
+ override public function set strand(value:IStrand):void
+ {
+ super.strand = value;
+
+ COMPILE::SWF {
+ _increment = new Button();
+ // Button(_increment).addBead(new UpArrowButtonView());
+ // Button(_increment).addBead(new ButtonAutoRepeatController());
+ _decrement = new Button();
+ // Button(_decrement).addBead(new DownArrowButtonView());
+ // Button(_decrement).addBead(new ButtonAutoRepeatController());
+
+ // Button(_increment).x = 0;
+ // Button(_increment).y = 0;
+ // Button(_decrement).x = 0;
+ // Button(_decrement).y = Button(_increment).height;
+
+ UIBase(_strand).addChild(_decrement);
+ UIBase(_strand).addChild(_increment);
+ rangeModel = _strand.getBeadByType(IBeadModel) as IRangeModel;
+ }
+
+ IEventDispatcher(value).addEventListener("widthChanged",sizeChangeHandler);
+ IEventDispatcher(value).addEventListener("heightChanged",sizeChangeHandler);
+
+ COMPILE::JS {
+ var host:UIBase = value as UIBase;
+ // depending on the surrounding layout, the element can be offset without this.
+ //host.element.style.position = "absolute";
+
+ _increment = new Button();
+ _increment.addClass("up");
+ _increment.text = '\u25B2';
+ host.addElement(_increment);
+ // _increment.positioner.style.display = 'block';
+
+ _decrement = new Button();
+ _decrement.addClass("down");
+ _decrement.text = '\u25BC';
+ // _decrement.positioner.style.display = 'block';
+ host.addElement(_decrement);
+
+// add this in CSS!
+ // controller = new SpinnerMouseController();
+ // host.addBead(controller);
+ }
+
+ COMPILE::SWF
+ {
+ var host:ILayoutChild = ILayoutChild(value);
+
+ // Complete the setup if the height is sized to content or has been explicitly set
+ // and the width is sized to content or has been explicitly set
+ if ((host.isHeightSizedToContent() || !isNaN(host.explicitHeight)) &&
+ (host.isWidthSizedToContent() || !isNaN(host.explicitWidth)))
+ sizeChangeHandler(null);
+ }
+ COMPILE::JS
+ {
+ // always run size change since there are no size change events
+ sizeChangeHandler(null);
+ }
+ }
+
+ /**
+ * The component for decrementing the org.apache.royale.jewel.Spinner value.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.9.3
+ */
+ COMPILE::SWF
+ public function get decrement():DisplayObject
+ {
+ return _decrement;
+ }
+ COMPILE::JS
+ public function get decrement():Button
+ {
+ return _decrement;
+ }
+
+ /**
+ * The component for incrementing the org.apache.royale.jewel.Spinner value.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.9.3
+ */
+ COMPILE::SWF
+ public function get increment():DisplayObject
+ {
+ return _increment;
+ }
+ COMPILE::JS
+ public function get increment():Button
+ {
+ return _increment;
+ }
+
+ /**
+ * @private
+ * @royaleignorecoercion org.apache.royale.core.UIBase
+ */
+ private function sizeChangeHandler( event:Event ) : void
+ {
+ var w:Number = UIBase(_strand).width;
+ var h:Number = UIBase(_strand).height / 2;
+ // _increment.width = w;
+ // _increment.height = h;
+ COMPILE::SWF
+ {
+ _increment.y = 0;
+ }
+ // _decrement.width = w;
+ // _decrement.height = h;
+ COMPILE::SWF
+ {
+ _decrement.y = h;
+ }
+ }
+ }
+}
diff --git a/frameworks/projects/Jewel/src/main/sass/components/_numericstepper.sass b/frameworks/projects/Jewel/src/main/sass/components/_numericstepper.sass
new file mode 100644
index 0000000..61db15e
--- /dev/null
+++ b/frameworks/projects/Jewel/src/main/sass/components/_numericstepper.sass
@@ -0,0 +1,59 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+// Jewel NumericStepper
+
+// NumericStepper variables
+
+.jewel.numericstepper
+ .jewel.textinput
+ display: inline-flex
+
+j|NumericStepper
+ IBeadModel: ClassReference("org.apache.royale.jewel.beads.models.RangeModel")
+ IBeadView: ClassReference("org.apache.royale.jewel.beads.views.NumericStepperView")
+
+@media -royale-swf
+ j|NumericStepper
+ // iBorderBead: ClassReference('org.apache.royale.html.beads.SingleLineBorderBead')
+ // iBackgroundBead: ClassReference('org.apache.royale.html.beads.SolidBackgroundBead')
+ // padding: 0px
+ // border-style: none
+
+
+// Jewel Spinner
+
+// Spinner variables
+.jewel.spinner
+ display: inline-flex
+ flex-direction: column
+ vertical-align: middle
+ .jewel.button
+ display: flex
+
+j|Spinner
+ IBeadModel: ClassReference("org.apache.royale.jewel.beads.models.RangeModel")
+ IBeadView: ClassReference("org.apache.royale.jewel.beads.views.SpinnerView")
+ IBeadController: ClassReference("org.apache.royale.jewel.beads.controllers.SpinnerMouseController")
+ // width: 16px
+ // height: 32px
+
+@media -royale-swf
+ j|Spinner
+ // IBeadController: ClassReference("org.apache.royale.html.beads.controllers.SpinnerMouseController")
\ No newline at end of file
diff --git a/frameworks/projects/Jewel/src/main/sass/defaults.sass b/frameworks/projects/Jewel/src/main/sass/defaults.sass
index 065a751..5a53044 100644
--- a/frameworks/projects/Jewel/src/main/sass/defaults.sass
+++ b/frameworks/projects/Jewel/src/main/sass/defaults.sass
@@ -39,6 +39,7 @@
@import "components/layout"
@import "components/list"
@import "components/navigation"
+@import "components/numericstepper"
@import "components/radiobutton"
@import "components/sectioncontent"
@import "components/slider"
diff --git a/frameworks/themes/JewelTheme/src/main/resources/defaults.css b/frameworks/themes/JewelTheme/src/main/resources/defaults.css
index 9390150..e3833e0 100644
--- a/frameworks/themes/JewelTheme/src/main/resources/defaults.css
+++ b/frameworks/themes/JewelTheme/src/main/resources/defaults.css
@@ -453,6 +453,34 @@ j|Card {
background-color: #ffffff;
}
+.jewel.numericstepper .jewel.textinput input {
+ width: 8em;
+ border-radius: 0.25rem 0px 0px 0.25rem;
+}
+
+.jewel.spinner .jewel.button {
+ color: transparent;
+ border-bottom-left-radius: 0px;
+ border-top-left-radius: 0px;
+ border-left: 0px;
+ padding: 6px;
+ height: 20px;
+}
+.jewel.spinner .jewel.button.up {
+ border-bottom-right-radius: 0px;
+}
+.jewel.spinner .jewel.button.up::after {
+ background-size: 40%;
+ background: url("data:image/svg+xml,%3Csvg viewBox='0 0 22 22' version='1.1' xmlns='http://www.w3.org/2000/svg'%3E%3Cg stroke='none' stroke-width='1' fill='none' fill-rule='evenodd'%3E%3Crect x='0' y='0' width='22' height='22'%3E%3C/rect%3E%3Cpath d='M18.3333333,2.75 L17.4166667,2.75 L17.4166667,0.916666667 L15.5833333,0.916666667 L15.5833333,2.75 L6.41666667,2.75 L6.41666667,0.916666667 L4.58333333,0.916666667 L4.58333333,2.75 L3.66666667,2.75 C2.65833333,2.75 1.83333333,3.575 1.83333 [...]
+}
+.jewel.spinner .jewel.button.down {
+ border-top-right-radius: 0px;
+}
+.jewel.spinner .jewel.button.down::after {
+ background-size: 40%;
+ background: url("data:image/svg+xml,%3Csvg viewBox='0 0 22 22' version='1.1' xmlns='http://www.w3.org/2000/svg'%3E%3Cg stroke='none' stroke-width='1' fill='none' fill-rule='evenodd'%3E%3Crect x='0' y='0' width='22' height='22'%3E%3C/rect%3E%3Cpath d='M18.3333333,2.75 L17.4166667,2.75 L17.4166667,0.916666667 L15.5833333,0.916666667 L15.5833333,2.75 L6.41666667,2.75 L6.41666667,0.916666667 L4.58333333,0.916666667 L4.58333333,2.75 L3.66666667,2.75 C2.65833333,2.75 1.83333333,3.575 1.83333 [...]
+}
+
.jewel.radiobutton input + span::before {
background: linear-gradient(white, #f3f3f3);
border: 1px solid #b3b3b3;
diff --git a/frameworks/themes/JewelTheme/src/main/sass/components-primary/_numericstepper.sass b/frameworks/themes/JewelTheme/src/main/sass/components-primary/_numericstepper.sass
new file mode 100644
index 0000000..5384f33
--- /dev/null
+++ b/frameworks/themes/JewelTheme/src/main/sass/components-primary/_numericstepper.sass
@@ -0,0 +1,61 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+// Jewel NumericStepper
+
+// NumericStepper variables
+$numericstepper-input-width: 8em
+$numericstepper-border-radius: $border-radius
+
+.jewel.numericstepper
+ .jewel.textinput
+ input
+ width: $numericstepper-input-width
+ border-radius: $numericstepper-border-radius 0px 0px $numericstepper-border-radius
+
+
+
+// Jewel Spinner
+
+// Spinner variables
+.jewel.spinner
+
+ .jewel.button
+ color: transparent
+ border-bottom-left-radius: 0px
+ border-top-left-radius: 0px
+ border-left: 0px
+
+ padding: 6px
+ height: 20px
+
+ &.up
+ border-bottom-right-radius: 0px
+
+ &::after
+ background-size: 40%
+ background: encodeSVG("<svg viewBox='0 0 22 22' version='1.1' xmlns='http://www.w3.org/2000/svg'><g stroke='none' stroke-width='1' fill='none' fill-rule='evenodd'><rect x='0' y='0' width='22' height='22'></rect><path d='M18.3333333,2.75 L17.4166667,2.75 L17.4166667,0.916666667 L15.5833333,0.916666667 L15.5833333,2.75 L6.41666667,2.75 L6.41666667,0.916666667 L4.58333333,0.916666667 L4.58333333,2.75 L3.66666667,2.75 C2.65833333,2.75 1.83333333,3.575 1.83333333,4.58333333 L1 [...]
+
+ &.down
+ border-top-right-radius: 0px
+
+ &::after
+ background-size: 40%
+ background: encodeSVG("<svg viewBox='0 0 22 22' version='1.1' xmlns='http://www.w3.org/2000/svg'><g stroke='none' stroke-width='1' fill='none' fill-rule='evenodd'><rect x='0' y='0' width='22' height='22'></rect><path d='M18.3333333,2.75 L17.4166667,2.75 L17.4166667,0.916666667 L15.5833333,0.916666667 L15.5833333,2.75 L6.41666667,2.75 L6.41666667,0.916666667 L4.58333333,0.916666667 L4.58333333,2.75 L3.66666667,2.75 C2.65833333,2.75 1.83333333,3.575 1.83333333,4.58333333 L1 [...]
+
\ No newline at end of file
diff --git a/frameworks/themes/JewelTheme/src/main/sass/defaults.sass b/frameworks/themes/JewelTheme/src/main/sass/defaults.sass
index de61c8a..9618266 100644
--- a/frameworks/themes/JewelTheme/src/main/sass/defaults.sass
+++ b/frameworks/themes/JewelTheme/src/main/sass/defaults.sass
@@ -41,6 +41,7 @@
@import "components-primary/label"
@import "components-primary/list"
@import "components-primary/navigation"
+@import "components-primary/numericstepper"
@import "components-primary/radiobutton"
@import "components-primary/slider"
@import "components-primary/table"