This is an automated email from the ASF dual-hosted git repository.
yishayw 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 e9ceb39f15 Added dropdown
new 445f28e322 Merge branch 'develop' of
https://github.com/apache/royale-asjs into develop
e9ceb39f15 is described below
commit e9ceb39f15a3ef03b509ee51d28e9529004aa452
Author: Yishay Weiss <[email protected]>
AuthorDate: Mon Apr 13 19:20:09 2026 +0300
Added dropdown
---
.../projects/Style/src/main/resources/defaults.css | 4 +
.../Style/src/main/resources/style-manifest.xml | 2 +
.../royale/org/apache/royale/style/Dropdown.as | 183 +++++++++++++++++++
.../org/apache/royale/style/skins/DropdownSkin.as | 200 +++++++++++++++++++++
.../org/apache/royale/style/skins/IDropdownSkin.as | 29 +++
.../style/stylebeads/states/FocusWithinState.as | 34 ++++
6 files changed, 452 insertions(+)
diff --git a/frameworks/projects/Style/src/main/resources/defaults.css
b/frameworks/projects/Style/src/main/resources/defaults.css
index 17ae0a005d..2e1c89a254 100644
--- a/frameworks/projects/Style/src/main/resources/defaults.css
+++ b/frameworks/projects/Style/src/main/resources/defaults.css
@@ -51,6 +51,10 @@ CheckBox
{
IStyleSkin:
ClassReference("org.apache.royale.style.skins.CheckBoxSkin");
}
+Dropdown
+{
+ IStyleSkin:
ClassReference("org.apache.royale.style.skins.DropdownSkin");
+}
DataItemRenderer
{
diff --git a/frameworks/projects/Style/src/main/resources/style-manifest.xml
b/frameworks/projects/Style/src/main/resources/style-manifest.xml
index 1dd68b067c..f881df56f1 100644
--- a/frameworks/projects/Style/src/main/resources/style-manifest.xml
+++ b/frameworks/projects/Style/src/main/resources/style-manifest.xml
@@ -28,6 +28,7 @@
<component id="Container" class="org.apache.royale.style.Container"/>
<component id="CheckBox" class="org.apache.royale.style.CheckBox"/>
<component id="Divider" class="org.apache.royale.style.Divider"/>
+ <component id="Dropdown" class="org.apache.royale.style.Dropdown"/>
<component id="FlexContainer" class="org.apache.royale.style.FlexContainer"/>
<component id="GridContainer" class="org.apache.royale.style.GridContainer"/>
<component id="StyleSkin" class="org.apache.royale.style.StyleSkin"/>
@@ -49,6 +50,7 @@
<component id="DataState"
class="org.apache.royale.style.stylebeads.states.attribute.DataState"/>
<component id="AriaState"
class="org.apache.royale.style.stylebeads.states.attribute.AriaState"/>
<component id="InertState"
class="org.apache.royale.style.stylebeads.states.attribute.InertState"/>
+ <component id="FocusWithinState"
class="org.apache.royale.style.stylebeads.states.FocusWithinState"/>
<component id="OpenState"
class="org.apache.royale.style.stylebeads.states.attribute.OpenState"/>
<component id="RTLState"
class="org.apache.royale.style.stylebeads.states.attribute.RTLState"/>
<component id="SelectedState"
class="org.apache.royale.style.stylebeads.states.attribute.SelectedState"/>
diff --git
a/frameworks/projects/Style/src/main/royale/org/apache/royale/style/Dropdown.as
b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/Dropdown.as
new file mode 100644
index 0000000000..77834d14df
--- /dev/null
+++
b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/Dropdown.as
@@ -0,0 +1,183 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.style
+{
+ COMPILE::JS
+ {
+ import org.apache.royale.core.WrappedHTMLElement;
+ }
+ import org.apache.royale.core.IChild;
+ import org.apache.royale.events.Event;
+ import org.apache.royale.style.elements.Div;
+ import org.apache.royale.style.skins.IDropdownSkin;
+ import org.apache.royale.style.StyleUIBase;
+
+ [Event(name="openChanged", type="org.apache.royale.events.Event")]
+
+ public class Dropdown extends Group
+ {
+ public function Dropdown()
+ {
+ super();
+ useWrapperStyle = true;
+ }
+
+ protected var triggerElem:Div;
+ protected var contentElem:Div;
+
+ private var _triggerText:String;
+
+ public function get triggerText():String
+ {
+ return _triggerText;
+ }
+
+ public function set triggerText(value:String):void
+ {
+ _triggerText = value;
+ if (triggerElem)
+ triggerElem.text = value;
+ }
+
+ private var _open:Boolean = false;
+
+ public function get open():Boolean
+ {
+ return _open;
+ }
+
+ public function set open(value:Boolean):void
+ {
+ if (value != _open)
+ {
+ _open = value;
+ toggleAttribute("open", value);
+ dispatchEvent(new Event("openChanged"));
+ }
+ }
+
+ private var _disabled:Boolean = false;
+
+ public function get disabled():Boolean
+ {
+ return _disabled;
+ }
+
+ public function set disabled(value:Boolean):void
+ {
+ if (value != _disabled)
+ {
+ _disabled = value;
+ toggleAttribute("data-disabled", value);
+ if (triggerElem)
+ {
+ COMPILE::JS
+ {
+ (triggerElem.element as
HTMLElement).tabIndex = value ? -1 : 0;
+ }
+ }
+ }
+ }
+
+ /**
+ * Override
numElements/addElementAt/getElementAt/getElementIndex
+ * so that MXML content goes into the content div, not the
wrapper.
+ */
+ override public function get numElements():int
+ {
+ return contentElem ? contentElem.numElements : 0;
+ }
+
+ override public function addElement(c:IChild,
dispatchEvent:Boolean = true):void
+ {
+ contentElem.addElement(c, dispatchEvent);
+ applyItemStyles(c);
+ }
+
+ override public function addElementAt(c:IChild, index:int,
dispatchEvent:Boolean = true):void
+ {
+ contentElem.addElementAt(c, index, dispatchEvent);
+ applyItemStyles(c);
+ }
+
+ override public function getElementAt(index:int):IChild
+ {
+ return contentElem.getElementAt(index);
+ }
+
+ override public function getElementIndex(c:IChild):int
+ {
+ return contentElem.getElementIndex(c);
+ }
+
+ COMPILE::JS
+ override protected function createElement():WrappedHTMLElement
+ {
+ var elem:WrappedHTMLElement = super.createElement();
+
+ triggerElem = new Div();
+ triggerElem.tabIndex = _disabled ? -1 : 0;
+ super.addElement(triggerElem);
+ if (_triggerText)
+ triggerElem.text = _triggerText;
+
+ contentElem = new Div();
+ super.addElement(contentElem);
+
+ if (_open)
+ toggleAttribute("open", true);
+ if (_disabled)
+ toggleAttribute("data-disabled", true);
+
+ element.addEventListener("focusout", handleFocusOut);
+
+ return elem;
+ }
+
+ COMPILE::JS
+ private function handleFocusOut(event:Object):void
+ {
+ // Close when focus leaves the dropdown entirely
+ if (_open && !element.contains(event.relatedTarget))
+ {
+ open = false;
+ }
+ }
+
+ /**
+ * @royaleignorecoercion
org.apache.royale.style.skins.IDropdownSkin
+ */
+ override protected function applySkin():void
+ {
+ var dropSkin:IDropdownSkin = skin as IDropdownSkin;
+ triggerElem.setStyles(dropSkin.triggerStyles, true);
+ contentElem.setStyles(dropSkin.contentStyles, true);
+ // Apply item styles to any children already added
+ for (var i:int = 0; i < numElements; i++)
+ {
+ applyItemStyles(getElementAt(i));
+ }
+ }
+
+ private function applyItemStyles(c:IChild):void
+ {
+ (c as StyleUIBase).setStyles((skin as
IDropdownSkin).itemStyles, true);
+ }
+ }
+}
diff --git
a/frameworks/projects/Style/src/main/royale/org/apache/royale/style/skins/DropdownSkin.as
b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/skins/DropdownSkin.as
new file mode 100644
index 0000000000..a5069aede8
--- /dev/null
+++
b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/skins/DropdownSkin.as
@@ -0,0 +1,200 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.style.skins
+{
+ import org.apache.royale.style.StyleSkin;
+ import org.apache.royale.style.Dropdown;
+ import org.apache.royale.core.IStrand;
+ import org.apache.royale.style.colors.ThemeColorSet;
+ import org.apache.royale.style.colors.ColorSwatch;
+ import org.apache.royale.style.util.ThemeManager;
+ import org.apache.royale.style.stylebeads.layout.Display;
+ import org.apache.royale.style.stylebeads.layout.Position;
+ import org.apache.royale.style.stylebeads.layout.Top;
+ import org.apache.royale.style.stylebeads.layout.Visibility;
+ import org.apache.royale.style.stylebeads.layout.ZIndex;
+ import org.apache.royale.style.stylebeads.effects.OpacityStyle;
+ import org.apache.royale.style.stylebeads.interact.Cursor;
+ import org.apache.royale.style.stylebeads.anim.Transition;
+ import org.apache.royale.style.stylebeads.background.BackgroundColor;
+ import org.apache.royale.style.stylebeads.border.BorderRadius;
+ import org.apache.royale.style.stylebeads.border.Border;
+ import org.apache.royale.style.stylebeads.border.BorderColor;
+ import org.apache.royale.style.stylebeads.border.BorderWidth;
+ import org.apache.royale.style.stylebeads.sizing.MinWidth;
+ import org.apache.royale.style.stylebeads.spacing.Margin;
+ import org.apache.royale.style.stylebeads.spacing.Padding;
+ import org.apache.royale.style.stylebeads.states.DisabledState;
+ import org.apache.royale.style.stylebeads.states.FocusWithinState;
+ import org.apache.royale.style.stylebeads.states.HoverState;
+ import org.apache.royale.style.stylebeads.states.attribute.OpenState;
+ import org.apache.royale.style.stylebeads.states.attribute.DataState;
+ import org.apache.royale.style.stylebeads.states.GroupPseudo;
+
+ public class DropdownSkin extends StyleSkin implements IDropdownSkin
+ {
+ public function DropdownSkin()
+ {
+ super();
+ }
+
+ /**
+ * @royaleignorecoercion org.apache.royale.style.Dropdown
+ */
+ private function get host():Dropdown
+ {
+ return _strand as Dropdown;
+ }
+
+ override public function set strand(value:IStrand):void
+ {
+ super.strand = value;
+ _styles = [
+ new Position("relative"),
+ new Display("inline-block")
+ ];
+ host.setStyles(_styles);
+ }
+
+ private var _triggerStyles:Array;
+
+ public function get triggerStyles():Array
+ {
+ if (!_triggerStyles)
+ createTriggerStyles();
+ return _triggerStyles;
+ }
+
+ public function set triggerStyles(value:Array):void
+ {
+ _triggerStyles = value;
+ }
+
+ private function createTriggerStyles():void
+ {
+ _triggerStyles = [
+ new Cursor("pointer"),
+ // When the wrapper has [data-disabled],
override the trigger cursor to default
+ new GroupPseudo([
+ new DataState("disabled", [
+ new Cursor("default")
+ ])
+ ], host.getWrapperStyle())
+ ];
+ }
+
+ private var _contentStyles:Array;
+
+ public function get contentStyles():Array
+ {
+ if (!_contentStyles)
+ createContentStyles();
+ return _contentStyles;
+ }
+
+ public function set contentStyles(value:Array):void
+ {
+ _contentStyles = value;
+ }
+
+ private function createContentStyles():void
+ {
+ var colorSet:ThemeColorSet =
ThemeManager.instance.activeTheme.themeColorSet;
+ var bgColor:ColorSwatch =
colorSet.getSwatch(ThemeColorSet.BASE, 100);
+ var borderColor:ColorSwatch =
colorSet.getSwatch(ThemeColorSet.NEUTRAL, 200);
+
+ var top:Top = new Top();
+ top.value = "100%";
+
+ var margin:Margin = new Margin();
+ margin.top = 1;
+
+ var padding:Padding = new Padding();
+ padding.block = 2;
+ padding.inline = 0;
+
+ _contentStyles = [
+ new Position("absolute"),
+ top,
+ new ZIndex(50),
+ new Visibility("hidden"),
+ new OpacityStyle(0),
+ new Transition(),
+ new MinWidth("12rem"),
+ new BackgroundColor(bgColor),
+ new BorderWidth(0.25),
+ new BorderColor(borderColor),
+ new
BorderRadius(ThemeManager.instance.activeTheme.radiusMD),
+ margin,
+ padding,
+ new GroupPseudo([
+ new FocusWithinState([
+ new Visibility("visible"),
+ new OpacityStyle(100)
+ ])
+ ], host.getWrapperStyle()),
+ new GroupPseudo([
+ new OpenState([
+ new Visibility("visible"),
+ new OpacityStyle(100)
+ ])
+ ], host.getWrapperStyle())
+ ];
+ }
+
+ private var _itemStyles:Array;
+
+ public function get itemStyles():Array
+ {
+ if (!_itemStyles)
+ createItemStyles();
+ return _itemStyles;
+ }
+
+ public function set itemStyles(value:Array):void
+ {
+ _itemStyles = value;
+ }
+
+ private function createItemStyles():void
+ {
+ var colorSet:ThemeColorSet =
ThemeManager.instance.activeTheme.themeColorSet;
+ var hoverBg:ColorSwatch =
colorSet.getSwatch(ThemeColorSet.BASE, 200);
+
+ var padding:Padding = new Padding();
+ padding.block = 2;
+ padding.inline = 3;
+
+ _itemStyles = [
+ new Cursor("pointer"),
+ padding,
+ new HoverState([
+ new BackgroundColor(hoverBg)
+ ])
+ ];
+ }
+
+ override public function update():void
+ {
+ _triggerStyles = null;
+ _contentStyles = null;
+ _itemStyles = null;
+ }
+ }
+}
diff --git
a/frameworks/projects/Style/src/main/royale/org/apache/royale/style/skins/IDropdownSkin.as
b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/skins/IDropdownSkin.as
new file mode 100644
index 0000000000..e030a44520
--- /dev/null
+++
b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/skins/IDropdownSkin.as
@@ -0,0 +1,29 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.style.skins
+{
+ import org.apache.royale.style.IStyleSkin;
+
+ public interface IDropdownSkin extends IStyleSkin
+ {
+ function get triggerStyles():Array;
+ function get contentStyles():Array;
+ function get itemStyles():Array;
+ }
+}
diff --git
a/frameworks/projects/Style/src/main/royale/org/apache/royale/style/stylebeads/states/FocusWithinState.as
b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/stylebeads/states/FocusWithinState.as
new file mode 100644
index 0000000000..2c6bc64610
--- /dev/null
+++
b/frameworks/projects/Style/src/main/royale/org/apache/royale/style/stylebeads/states/FocusWithinState.as
@@ -0,0 +1,34 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.style.stylebeads.states
+{
+ /**
+ * The FocusWithinState class is a style decorator that applies styles
when
+ * any child of the element has focus (:focus-within pseudo-class).
+ */
+ public class FocusWithinState extends LeafDecorator
+ {
+ public function FocusWithinState(styles:Array = null)
+ {
+ super(styles);
+ selectorDecorator = "focus-within:";
+ ruleDecorator = ":focus-within";
+ }
+ }
+}