xooie 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 828457f85e8912c580dea1bfa855408d5bf3cf3e
4
+ data.tar.gz: 69bd8050bf199eba84e62ec7c3be7be91af1f82b
5
+ SHA512:
6
+ metadata.gz: 7f4ffef30449bf41ddebe633268afd4c04a01fc516dc1b0b73a9f2439da0c0c2b8dc36805689bb0897157bcca6604bc84d6aabfb852c378c3078a13a59f5ba88
7
+ data.tar.gz: bb0c5c49d9fcd04b49a47cdca180fe7d848b635f63fd1da8ecd1d6fed0af55e2dcd0bc6ef42375047a30bb98e0a2a8b01d1001370873408f7b97200d636c75cf
@@ -15,7 +15,7 @@
15
15
  */
16
16
 
17
17
  define('xooie/dropdown', ['jquery', 'xooie/base'], function($, Base) {
18
-
18
+
19
19
  var parseWhich = function(which) {
20
20
  if (typeof which === 'string') {
21
21
  which = which.split(',');
@@ -150,8 +150,12 @@ define('xooie/dropdown', ['jquery', 'xooie/base'], function($, Base) {
150
150
  }
151
151
  };
152
152
 
153
+ Dropdown.prototype.getNamespacedTrigger = function(trigger, state){
154
+ return trigger + '.' + state + 'XooieDropdown';
155
+ };
156
+
153
157
  Dropdown.prototype.addHandlers = function(state, index){
154
- var trigger, handle, triggerData, countName;
158
+ var trigger, nsTrigger, handle, triggerData, countName;
155
159
 
156
160
  triggerData = this.options.triggers[state];
157
161
 
@@ -166,12 +170,14 @@ define('xooie/dropdown', ['jquery', 'xooie/base'], function($, Base) {
166
170
 
167
171
  handle.data(countName, handle.data(countName) + 1 || 1);
168
172
 
169
- handle.on(trigger, $.extend({delay: 0, index: index}, triggerData[trigger]), this.handlers[state]);
173
+ nsTrigger = this.getNamespacedTrigger(trigger, state);
174
+
175
+ handle.on(nsTrigger, $.extend({delay: 0, index: index}, triggerData[trigger]), this.handlers[state]);
170
176
  }
171
177
  };
172
178
 
173
179
  Dropdown.prototype.removeHandlers = function(state, index){
174
- var trigger, handle, triggerData, countName, eventCount;
180
+ var trigger, nsTrigger, handle, triggerData, countName, eventCount;
175
181
 
176
182
  triggerData = this.options.triggers[state];
177
183
 
@@ -183,7 +189,9 @@ define('xooie/dropdown', ['jquery', 'xooie/base'], function($, Base) {
183
189
  eventCount = handle.data(countName) - 1;
184
190
 
185
191
  if (eventCount <= 0) {
186
- handle.unbind(trigger, this.handlers[state]);
192
+ nsTrigger = this.getNamespacedTrigger(trigger, state);
193
+
194
+ handle.unbind(nsTrigger);
187
195
 
188
196
  handle.data(countName, 0);
189
197
  } else {
@@ -0,0 +1,83 @@
1
+ /*
2
+ * Copyright 2012 Comcast
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ define('xooie/event_handler', ['jquery', 'xooie/helpers'], function($, helpers) {
18
+
19
+ var EventHandler = function(namespace) {
20
+ this.namespace = namespace;
21
+
22
+ this.handlers = {};
23
+
24
+ this._callbacks = {};
25
+ };
26
+
27
+ function format(type, namespace) {
28
+ if (!namespace) {
29
+ return type;
30
+ } else {
31
+ return type + '.' + namespace;
32
+ }
33
+ }
34
+
35
+ EventHandler.prototype.add = function(type, method) {
36
+ var self = this,
37
+ formattedType, t;
38
+
39
+ if (helpers.isObject(type) && helpers.isUndefined(method)) {
40
+ for(t in type) {
41
+ if (helpers.isFunction(type[t])) {
42
+ this.add(t, type[t]);
43
+ }
44
+ }
45
+
46
+ return;
47
+ }
48
+
49
+ formattedType = format(type, this.namespace);
50
+
51
+ if (helpers.isUndefined(this.handlers[formattedType])) {
52
+ this.handlers[formattedType] = function(e) {
53
+ self.fire(e, this, arguments);
54
+ };
55
+ }
56
+
57
+ if (helpers.isUndefined(this._callbacks[type])) {
58
+ this._callbacks[type] = $.Callbacks('unique');
59
+ }
60
+
61
+ this._callbacks[type].add(method);
62
+ };
63
+
64
+ EventHandler.prototype.clear = function(type) {
65
+ delete(this.handlers[format(type, this.namespace)]);
66
+
67
+ if (!helpers.isUndefined(this._callbacks[type])) {
68
+ this._callbacks[type].empty();
69
+ }
70
+ };
71
+
72
+ EventHandler.prototype.fire = function(event, context, args) {
73
+ if (event.namespace && event.namespace !== this.namespace) {
74
+ return;
75
+ }
76
+
77
+ if (!helpers.isUndefined(this._callbacks[event.type])) {
78
+ this._callbacks[event.type].fireWith(context, args);
79
+ }
80
+ };
81
+
82
+ return EventHandler;
83
+ });
@@ -0,0 +1,61 @@
1
+ /*
2
+ * Copyright 2012 Comcast
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ /**
18
+ * class Xooie.helpers
19
+ *
20
+ * A collection of helper methods used by Xooie modules.
21
+ **/
22
+
23
+ define('xooie/helpers', ['jquery'], function($){
24
+ var helpers = {};
25
+ /**
26
+ * Xooie.helpers.toAry(str) -> Array
27
+ * - str (String | Array): The string to be converted to an array, or an array.
28
+ *
29
+ * Converts a string to an array, or returns the passed argument if it is already an array. Used
30
+ * when parsing data attributes that can be either a space-delineated string or an array.
31
+ **/
32
+ helpers.toAry = function(str) {
33
+ if (typeof str === 'string') {
34
+ return str.split(/\s+/);
35
+ } else if (str instanceof Array) {
36
+ return str;
37
+ }
38
+ };
39
+
40
+ helpers.toInt = function(int) {
41
+ return parseInt(int, 10);
42
+ };
43
+
44
+ helpers.isArray = Array.isArray || function(ary) {
45
+ return Array.prototype.toString(ary) === '[object Array]';
46
+ };
47
+
48
+ helpers.isObject = function(obj) {
49
+ return Object.prototype.toString(obj) === '[object Object]';
50
+ };
51
+
52
+ helpers.isUndefined = function(obj) {
53
+ return obj === void 0;
54
+ };
55
+
56
+ helpers.isFunction = function(func) {
57
+ return typeof func === 'function';
58
+ };
59
+
60
+ return helpers;
61
+ });
@@ -0,0 +1,216 @@
1
+ define('xooie/keyboard_navigation', ['jquery', 'xooie/helpers'], function($, helpers){
2
+ var selectors, keyboardNavigation, keybindings;
3
+
4
+
5
+ keybindings = {
6
+ 37: function(event) {
7
+ moveFocus($(event.target), -1);
8
+
9
+ event.preventDefault();
10
+ },
11
+
12
+ 38: function() {
13
+
14
+ },
15
+
16
+ 39: function(event) {
17
+ moveFocus($(event.target), 1);
18
+
19
+ event.preventDefault();
20
+ },
21
+
22
+ 40: function() {
23
+
24
+ }
25
+ };
26
+
27
+ /** internal
28
+ * Xooie.Widget._moveFocus(direction)
29
+ * - direction (Integer): Determines whether or not to increment or decrement the index. Can be 1 or -1.
30
+ *
31
+ * Moves focus to either the next or previous focusable item, if available. Focus order follows the
32
+ * tab order of the page (items without tabindex or tabindex=0 will be focused before tabindex=1). Focusable
33
+ * items with a tabindex=-1 will not be focused.
34
+ **/
35
+ function moveFocus(current, direction) {
36
+ // TODO: Clean this up. It's a mess
37
+ // TODO: Write tests.
38
+ // TODO: Add detection of new contexts
39
+ // TODO: Add recollection of last focused item
40
+
41
+ var selector, selectors, tabindex, index, target;
42
+
43
+ var tabIndicies= [];
44
+
45
+ selectors = {
46
+ unindexed: ['[data-widget-type] a[href]:visible:not(:disabled):not([tabindex])',
47
+ '[data-widget-type] button:visible:not(:disabled):not([tabindex])',
48
+ '[data-widget-type] input:visible:not(:disabled):not([tabindex])',
49
+ '[data-widget-type] select:visible:not(:disabled):not([tabindex])',
50
+ '[data-widget-type] textarea:visible:not(:disabled):not([tabindex])',
51
+ '[data-widget-type] [tabindex=0]:visible:not(:disabled)'].join(','),
52
+ indexed: function(t) {
53
+ if (t > 0) {
54
+ return '[data-widget-type] [tabindex=' + t + ']:visible:not(:disabled)';
55
+ }
56
+ },
57
+ allIndexed: '[data-widget-type] [tabindex]:visible:not(:disabled)'
58
+ };
59
+
60
+ // jquery select the current item
61
+ current = $(current);
62
+
63
+ // we may not be focused on anything. If that's the case, focus on the first focusable item
64
+ if (!current.is(selectors.unindexed) && !current.is(selectors.allIndexed)) {
65
+ // get the lowest tabindex
66
+ $(selectors.allIndexed).each(function(){
67
+ var i = helpers.toInt($(this).attr('tabindex'));
68
+
69
+ if (tabIndicies.indexOf(i) === -1 && i > 0) {
70
+ tabIndicies.push(i);
71
+ }
72
+ });
73
+
74
+ if (tabIndicies.length > 0) {
75
+ tabIndicies.sort(function(a,b) { return a-b; });
76
+
77
+ target = $(selectors.indexed(tabIndicies[0])).first();
78
+ } else {
79
+ target = $(selectors.unindexed).first();
80
+ }
81
+
82
+ if (target.length > 0) {
83
+ target.focus();
84
+
85
+ return;
86
+ }
87
+ }
88
+
89
+ // get the current tabindex
90
+ tabindex = helpers.toInt(current.attr('tabindex'));
91
+
92
+ // check if tabindex is a number and not 0...
93
+ if (!tabindex) {
94
+ // if it is not, assume we're on an element that has no tab index and select other such elements
95
+ selector = selectors.unindexed;
96
+ } else {
97
+ // otherwise, select all items that are of the same tabindex
98
+ selector = selectors.indexed(tabindex);
99
+ }
100
+
101
+ // find the index of the current item
102
+ index = current.index(selector);
103
+
104
+ if (index + direction >= 0) {
105
+ // get the next/previous item
106
+ target = $(selector).eq(index + direction);
107
+
108
+ // Check to see if we have a valid target...
109
+ if (target.length > 0) {
110
+ // if it is, focus the target and return
111
+ target.focus();
112
+
113
+ return;
114
+ }
115
+ }
116
+
117
+ // if it is not, then we have several possibilities:
118
+
119
+ // If the direction is 1 and tabindex is not a number or 0, then we are at the end of the tab order. Do nothing.
120
+ if (direction === 1 && !tabindex) {
121
+ return;
122
+ // If the direction is 1 and the tabindex is a number, then we need to check for the presence of the next tabindex
123
+ } else if (direction === 1 && !isNaN(tabindex)) {
124
+ // Loop through all elements with a tab index
125
+ $(selectors.allIndexed).each(function() {
126
+ // Build a collection of all tab indicies greater than the current tab index:
127
+ var i = helpers.toInt($(this).attr('tabindex'));
128
+
129
+ if (i > tabindex && tabIndicies.indexOf(i) === -1 && i > 0) {
130
+ tabIndicies.push(i);
131
+ }
132
+ });
133
+
134
+ // If there are tab indicies that are greater than the current one...
135
+ if (tabIndicies.length > 0) {
136
+ // sort our tab indicies ascending
137
+ tabIndicies.sort(function(a, b) { return a-b; });
138
+
139
+ // we now have our new tab index
140
+ tabindex = tabIndicies[0];
141
+
142
+ // Get the first item of the new tab index
143
+ target = $(selectors.indexed(tabindex)).first();
144
+ } else {
145
+ // Otherwise, select the first unindexed item
146
+ target = $(selectors.unindexed).first();
147
+ }
148
+
149
+ } else if (direction === -1 && isNaN(tabindex)) {
150
+ // In this case, we are at the first non-indexed focusable item. We need to find the last indexed item.
151
+ // Loop through all elements with a tab index
152
+ $(selectors.allIndexed).each(function() {
153
+ var i = helpers.toInt($(this).attr('tabindex'));
154
+ // Build a collection of all tab indicies
155
+ if (tabIndicies.indexOf(i) === -1) {
156
+ tabIndicies.push(i);
157
+ }
158
+ });
159
+
160
+ if (tabIndicies.length > 0) {
161
+ // sort our tab indicies descending
162
+ tabIndicies.sort(function(a, b) { return b-a; });
163
+
164
+ // we now have our new tab index
165
+ tabindex = tabIndicies[0];
166
+
167
+ // Select the last indexed item
168
+ target = $(selectors.indexed(tabindex)).last();
169
+ }
170
+ } else if (direction === -1 && !isNaN(tabindex) && tabindex > 0) {
171
+ $(selectors.allIndexed).each(function(){
172
+ var i = helpers.toInt($(this).attr('tabindex'));
173
+
174
+ if (i < tabindex && tabIndicies.indexOf(i) === -1 && i > 0) {
175
+ tabIndicies.push(i);
176
+ }
177
+ });
178
+
179
+ if (tabIndicies.length > 0) {
180
+ // sort our tab indicies asceding
181
+ tabIndicies.sort(function(a, b) { return a-b; });
182
+
183
+ // we now have our new tab index
184
+ tabindex = tabIndicies[0];
185
+
186
+ // Select the last indexed item
187
+ target = $(selectors.indexed(tabindex)).last();
188
+ }
189
+ }
190
+
191
+ if (!helpers.isUndefined(target)) {
192
+ // assuming we have a target, focus it.
193
+ target.focus();
194
+ }
195
+
196
+ }
197
+
198
+ var instantiated;
199
+
200
+ keyboardNavigation = function(){
201
+ if (instantiated) {
202
+ return instantiated;
203
+ }
204
+
205
+ $(document).on('keyup', function(event) {
206
+ if (helpers.isFunction(keybindings[event.which])) {
207
+ keybindings[event.which](event);
208
+ }
209
+ });
210
+
211
+ instantiated = this;
212
+ };
213
+
214
+ return keyboardNavigation;
215
+
216
+ });
@@ -0,0 +1,193 @@
1
+ /**
2
+ * class Xooie.shared
3
+ *
4
+ * A module that contains functionality that is used both by [[Xooie.Widget]] and [[Xooie.Addon]]
5
+ * This module exists to abstract common functionality so that it can be maintained in one place.
6
+ * It is not intended to be used independently.
7
+ **/
8
+ define('xooie/shared', ['jquery'], function($){
9
+
10
+ /** internal
11
+ * Xooie.shared.propertyDetails(name) -> Object
12
+ * - name (String): The name of the property
13
+ *
14
+ * Generates a hash of attributes that will be used in setting and getting the property.
15
+ *
16
+ * ##### Return values
17
+ *
18
+ * - **getter** (String): The name of the internal getter method for this property.
19
+ * `_get_name`
20
+ * - **setter** (String): The name of the internal setter method for this property.
21
+ * `_set_name`
22
+ * - **processor** (String): The name of the internal processor method for this property.
23
+ * `_process_name`
24
+ * - **validator** (String): The name of the internal validator method for this property.
25
+ * `_validate_name`
26
+ * **default** (String): The name of the internally stored default value for this property.
27
+ * `_default_name`
28
+ * - **value** (String): The name of the internally stored value for this property.
29
+ * `_name`
30
+ **/
31
+ function propertyDetails (name) {
32
+ return {
33
+ getter: '_get_' + name,
34
+ setter: '_set_' + name,
35
+ processor: '_process_' + name,
36
+ validator: '_validate_' + name,
37
+ defaultValue: '_default_value_' + name,
38
+ value: '_' + name
39
+ };
40
+ }
41
+
42
+ /** internal
43
+ * Xooie.shared.propertyDispatcher(name, prototype)
44
+ * - name (String): The name of the property
45
+ * - prototype (Object): The prototype of the [[Xooie.Widget]] or [[Xooie.Addon]] for which the property is being set.
46
+ *
47
+ * Gets the [[Xooie.shared.propertyDetails]] for the property, adds the `name` to the list of [[Xooie.Widget#_definedProps]]
48
+ * (or [[Xooie.Addon#_definedProps]]). Adds a method called `name` to the prototype that allows this property to be set or
49
+ * retrieved.
50
+ **/
51
+ function propertyDispatcher (name, prototype) {
52
+ var prop = propertyDetails(name);
53
+
54
+ if (typeof prototype[name] !== 'function') {
55
+ prototype._definedProps.push(name);
56
+
57
+ prototype[name] = function(value) {
58
+ if (typeof value === 'undefined') {
59
+ return this[prop.getter]();
60
+ } else {
61
+ return this[prop.setter](value);
62
+ }
63
+ };
64
+ }
65
+ }
66
+
67
+ var shared = {
68
+ /**
69
+ * Xooie.shared.defineReadOnly(module, name[, defaultValue])
70
+ * - module (Widget | Addon): The module on which this property will be defined.
71
+ * - name (String): The name of the property to define as a read-only property.
72
+ * - defaultValue (Object): An optional default value.
73
+ *
74
+ * Defines a read-only property that can be accessed either by [[Xooie.Widget#get]]/[[Xooie.Addon#get]] or
75
+ * calling the `{{name}}` method on the instance of the module.
76
+ **/
77
+ defineReadOnly: function(module, name, defaultValue){
78
+ var prop = propertyDetails(name);
79
+
80
+ propertyDispatcher(name, module.prototype);
81
+
82
+ //The default value is reset each time this method is called;
83
+ module.prototype[prop.defaultValue] = defaultValue;
84
+
85
+ if (typeof module.prototype[prop.getter] !== 'function') {
86
+ module.prototype[prop.getter] = function() {
87
+ var value = typeof this[prop.value] !== 'undefined' ? this[prop.value] : this[prop.defaultValue];
88
+
89
+ if (typeof this[prop.processor] === 'function') {
90
+ return this[prop.processor](value);
91
+ }
92
+
93
+ return value;
94
+ };
95
+ }
96
+ },
97
+ /**
98
+ * Xooie.shared.defineWriteOnly(module, name)
99
+ * - module (Widget | Addon): The module on which this property will be defined.
100
+ * - name (String): The name of the property to define as a write-only property
101
+ *
102
+ * Defines a write-only property that can be set using [[Xooie.Widget#set]]/[[Xooie.Addon#set]] or by passing
103
+ * a value to the `{{name}}` method on the instance of the module.
104
+ **/
105
+ defineWriteOnly: function(module, name){
106
+ var prop = propertyDetails(name);
107
+
108
+ propertyDispatcher(name, module.prototype);
109
+
110
+ if (typeof module.prototype[prop.setter] !== 'function') {
111
+ module.prototype[prop.setter] = function(value){
112
+ if (typeof this[prop.validator] !== 'function' || this[prop.validator](name)) {
113
+ this[prop.value] = value;
114
+ }
115
+ };
116
+ }
117
+ },
118
+ /**
119
+ * Xooie.shared.extend(constr, _super) -> Widget | Addon
120
+ * - constr (Function): The constructor for the new [[Xooie.Widget]] or [[Xooie.Addon]] class.
121
+ * - _super (Widget | Addon): The module which is to be extended
122
+ *
123
+ * Creates a new Xooie widget/addon class that inherits all properties from the extended class.
124
+ * Constructors for the class are called in order from the top-level constructor to the
125
+ * base constructor.
126
+ **/
127
+ extend: function(constr, module){
128
+ var newModule = (function(){
129
+ return function Child() {
130
+ module.apply(this, arguments);
131
+ constr.apply(this, arguments);
132
+ this._extendCount -= 1;
133
+ };
134
+ })();
135
+
136
+
137
+ $.extend(true, newModule, module);
138
+ $.extend(true, newModule.prototype, module.prototype);
139
+
140
+ newModule.prototype._extendCount = newModule.prototype._extendCount === null ? 1 : newModule.prototype._extendCount += 1;
141
+
142
+ return newModule;
143
+ },
144
+ /**
145
+ * Xooie.shared.get(instance, name) -> object
146
+ * - instance (Widget | Addon): The instance from which the property is to be retrieved.
147
+ * - name (String): The name of the property to be retrieved.
148
+ *
149
+ * Retrieves the value of the property. Returns `undefined` if the property has not been defined.
150
+ **/
151
+ get: function(instance, name){
152
+ var prop = propertyDetails(name);
153
+
154
+ return instance[prop.getter]();
155
+ },
156
+ /**
157
+ * Xooie.shared.set(instance, name, value)
158
+ * - instance (Widget | Addon): The instance where the property is being set.
159
+ * - name (String): The name of the property to be set.
160
+ * - value: The value of the property to be set.
161
+ *
162
+ * Sets a property, so long as that property has been defined.
163
+ **/
164
+ set: function(instance, name, value){
165
+ var prop = propertyDetails(name);
166
+
167
+ if (typeof instance[prop.setter] === 'function') {
168
+ instance[prop.setter](value);
169
+ }
170
+ },
171
+
172
+ /**
173
+ * Xooie.shared.setData(instance, data)
174
+ * - instance (Widget | Addon): The instance to set data on
175
+ * - data (Object): A collection of key/value pairs
176
+ *
177
+ * Sets the properties to the values specified, as long as the property has been defined
178
+ **/
179
+ setData: function(instance, data) {
180
+ var i, prop;
181
+
182
+ for (i = 0; i < instance._definedProps.length; i++) {
183
+ prop = instance._definedProps[i];
184
+ if (typeof data[prop] !== 'undefined') {
185
+ instance.set(prop, data[prop]);
186
+ }
187
+ }
188
+ }
189
+
190
+ };
191
+
192
+ return shared;
193
+ });
@@ -0,0 +1,32 @@
1
+ define('xooie/widgets/accordion', ['jquery', 'xooie/widgets/tab'], function($, Tab){
2
+ var Accordion = Tab.extend(function() {
3
+ });
4
+
5
+ Accordion.define('namespace', 'accordion');
6
+
7
+ /** internal
8
+ * Xooie.Accordion#_process_role_tablist(tablist) -> Element
9
+ * - tablist (Element): A jQuery-selected collection of [[Xooie.Tab#tablists]]
10
+ *
11
+ * Same as [[Xooie.Tab#_process_role_tablist]] and also adds the [`aria-multiselectable="true"`](http://www.w3.org/TR/wai-aria/states_and_properties#aria-multiselectable) attribute.
12
+ **/
13
+ Accordion.prototype._process_role_tablist = function(tablist) {
14
+ Tab.prototype._process_role_tablist.apply(this, arguments);
15
+
16
+ tablist.attr('aria-multiselectable', true);
17
+
18
+ return tablist;
19
+ };
20
+
21
+ Accordion.prototype.selectTabs = function(event, selectedTab) {
22
+ var activeTabs = this.getActiveTabs();
23
+
24
+ if (activeTabs.is(selectedTab)) {
25
+ return activeTabs.not(selectedTab);
26
+ } else {
27
+ return activeTabs.add(selectedTab);
28
+ }
29
+ };
30
+
31
+ return Accordion;
32
+ });