@rivtn/noseur 1.0.0 → 1.0.1

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.
@@ -435,3 +435,29 @@ input.noseur-fctrl-cc {
435
435
  padding: 0px 7px;
436
436
  margin: 0px 15px -6px 15px;
437
437
  }
438
+
439
+ /* ColorPicker */
440
+ .noseur-color-picker-modal,
441
+ .noseur-color-picker-inline,
442
+ .noseur-color-picker-popover {
443
+ padding: 15px;
444
+ border-radius: 7px;
445
+ border: 1px solid var(--noseurSchemeDataBorderColor, rgb(145, 144, 144));
446
+ }
447
+
448
+ .noseur-color-picker-modal {
449
+ width: auto !important;
450
+ padding: 0px !important;
451
+ }
452
+
453
+ .noseur-color-picker-modal .noseur-color-picker-layout-column {
454
+ flex: 1;
455
+ }
456
+
457
+ .noseur-color-picker-popover {
458
+ background: var(--containerBackground, white);
459
+ }
460
+
461
+ .noseur-color-picker-popover {
462
+ margin: 15px;
463
+ }
@@ -1,9 +1,9 @@
1
1
  import "../Composed.css";
2
2
  import React from "react";
3
- import { ColorEventHandler } from "../../constants/Types";
3
+ import { Color, ColorEventHandler } from "../../constants/Types";
4
4
  import { ComponentBaseProps, ComponentRenderType } from "../../core/ComponentBaseProps";
5
- import { DialogProps } from "../../overlay/Dialog";
6
- import { PopoverProps } from "../../overlay/Popover";
5
+ import { DialogManageRef, DialogProps } from "../../overlay/Dialog";
6
+ import { PopoverManageRef, PopoverProps } from "../../overlay/Popover";
7
7
  export declare enum ColorPickerLayoutElement {
8
8
  DashElement = "[d]",
9
9
  SpaceElement = "[s]",
@@ -31,10 +31,17 @@ export type ColorPickerAttributesRelays = {
31
31
  popover?: Partial<PopoverProps>;
32
32
  };
33
33
  export interface ColorPickerManageRef {
34
+ reset: () => void;
35
+ dialogManageRef: () => DialogManageRef | null;
36
+ popoverManageRef: () => PopoverManageRef | null;
37
+ toggle: (event: Event, target?: HTMLElement) => void;
34
38
  }
35
39
  export interface ColorPickerProps extends ComponentBaseProps<HTMLDivElement, ColorPickerManageRef, ColorPickerAttributesRelays> {
40
+ colors: Color;
41
+ alpha: number;
36
42
  autoFocus: boolean;
37
43
  modalVisible: boolean;
44
+ selectedColors: Color[];
38
45
  type: ComponentRenderType;
39
46
  onSelectColor: ColorEventHandler;
40
47
  }
@@ -1,6 +1,17 @@
1
1
  import "../Composed.css";
2
2
  import React from "react";
3
3
  import { ComponentRenderType } from "../../core/ComponentBaseProps";
4
+ import { Dialog } from "../../overlay/Dialog";
5
+ import { Popover } from "../../overlay/Popover";
6
+ import { ObjectHelper } from "../../utils/ObjectHelper";
7
+ import { Classname } from "../../utils/Classname";
8
+ import { ColorMap } from "../../form/ColorMap";
9
+ import { ColorSlider, ColorSliderGradient } from "./ColorSlider";
10
+ import { FormControl } from "../form/FormControl";
11
+ import { ColorPalette } from "../../form/ColorPalette";
12
+ import { TextInput } from "../../form/Input";
13
+ import { Orientation } from "../../constants/Orientation";
14
+ import { ColorHelper } from "../../utils/ColorHelper";
4
15
  export var ColorPickerLayoutElement;
5
16
  (function (ColorPickerLayoutElement) {
6
17
  ColorPickerLayoutElement["DashElement"] = "[d]";
@@ -26,9 +37,13 @@ export var ColorPickerLayout;
26
37
  (function (ColorPickerLayout) {
27
38
  })(ColorPickerLayout || (ColorPickerLayout = {}));
28
39
  class ColorPickerComponent extends React.Component {
29
- static defaultProps = {};
40
+ static defaultProps = {
41
+ alpha: 1,
42
+ };
30
43
  state = {
44
+ alpha: this.props.alpha,
31
45
  modalVisible: this.props.modalVisible,
46
+ selectedColors: this.props.selectedColors ?? [this.props.colors ?? ColorHelper.hexToColor("#000000")]
32
47
  };
33
48
  dialogManageRef = {};
34
49
  popoverManageRef = {};
@@ -40,6 +55,14 @@ class ColorPickerComponent extends React.Component {
40
55
  this.reportOnSelectColor = this.reportOnSelectColor.bind(this);
41
56
  this.performColorControlAction = this.performColorControlAction.bind(this);
42
57
  }
58
+ componentDidMount() {
59
+ ObjectHelper.resolveManageRef(this, {
60
+ toggle: this.toggle,
61
+ reset: () => alert("RESET"),
62
+ dialogManageRef: () => this.dialogManageRef,
63
+ popoverManageRef: () => this.popoverManageRef,
64
+ });
65
+ }
43
66
  toggle(event, target) {
44
67
  switch (this.props.type) {
45
68
  case ComponentRenderType.MODAL:
@@ -72,14 +95,366 @@ class ColorPickerComponent extends React.Component {
72
95
  break;
73
96
  }
74
97
  }
75
- reportOnSelectColor(hex) {
76
- if (!this.props.onSelectColor)
77
- return;
78
- throw new Error("Implement report on select color " + hex);
79
- }
80
98
  toggleMapComponent() {
81
99
  }
82
100
  togglePalleteElement() {
83
101
  }
102
+ reportOnSelectColor(color) {
103
+ const previousColor = this.state.selectedColors?.[0];
104
+ this.setState({ selectedColors: [color] });
105
+ this.props.onSelectColor?.({ color, previousColor });
106
+ }
107
+ /*buildLayoutElements(controlActionMap: NoseurObject<(e?: any) => void>) {
108
+ const layoutElements: NoseurObject<NoseurElement> = {};
109
+ const requiredLayoutElements = new Set<DateTimePickerLayoutElement>();
110
+ this.props.layout.split(" ").forEach(l => requiredLayoutElements.add(l as any));
111
+ this.props.topLayout.split(" ").forEach(l => requiredLayoutElements.add(l as any));
112
+ this.props.timeLayout.split(" ").forEach(l => requiredLayoutElements.add(l as any));
113
+ this.props.leftLayout.split(" ").forEach(l => requiredLayoutElements.add(l as any));
114
+ this.props.rightLayout.split(" ").forEach(l => requiredLayoutElements.add(l as any));
115
+ this.props.footerLayout.split(" ").forEach(l => requiredLayoutElements.add(l as any));
116
+ this.props.headerLayout.split(" ").forEach(l => requiredLayoutElements.add(l as any));
117
+ this.props.bottomLayout.split(" ").forEach(l => requiredLayoutElements.add(l as any));
118
+ this.props.yearModeLayout.split(" ").forEach(l => requiredLayoutElements.add(l as any));
119
+ this.props.selectionLayout.split(" ").forEach(l => requiredLayoutElements.add(l as any));
120
+ this.props.monthModeLayout.split(" ").forEach(l => requiredLayoutElements.add(l as any));
121
+ this.props.yearModeHeaderLayout.split(" ").forEach(l => requiredLayoutElements.add(l as any));
122
+ this.props.yearModeHeaderLayout.split(" ").forEach(l => requiredLayoutElements.add(l as any));
123
+ this.props.monthModeHeaderLayout.split(" ").forEach(l => requiredLayoutElements.add(l as any));
124
+ this.props.monthModeHeaderLayout.split(" ").forEach(l => requiredLayoutElements.add(l as any));
125
+ const excludedLayouts = [
126
+ DateTimePickerLayoutElement.TimeElement, DateTimePickerLayoutElement.WeekDayElement,
127
+ DateTimePickerLayoutElement.DayElement, DateTimePickerLayoutElement.SelectionElement,
128
+ DateTimePickerLayoutElement.LeftPanelElement, DateTimePickerLayoutElement.HeaderElement,
129
+ DateTimePickerLayoutElement.FooterElement, DateTimePickerLayoutElement.RightPanelElement,
130
+ DateTimePickerLayoutElement.TopPanelElement, DateTimePickerLayoutElement.BottomPanelElement,
131
+ DateTimePickerLayoutElement.YearModeHeaderElement, DateTimePickerLayoutElement.YearModeFooterElement,
132
+ DateTimePickerLayoutElement.MonthModeHeaderElement, DateTimePickerLayoutElement.MonthModeFooterElement,
133
+ ];
134
+ const activeYear = this.state.activeDate.getFullYear();
135
+ const selectedYear = (this.state.selectedDates.length ? this.state.selectedDates[0] : new Date()).getFullYear();
136
+ const controlPropsMap: NoseurObject<Partial<ButtonProps> | NoseurElement> = {
137
+ DayElement: this.props.dayControl,
138
+ NextElement: this.props.nextControl,
139
+ PreviousElement: this.props.prevControl,
140
+ IncrementElement: this.props.incrementControl,
141
+ DecrementElement: this.props.decrementControl,
142
+ };
143
+ // TODO mltiple for multiple calender months
144
+ formattedDate.disabled = formattedDate.isNotInMonth;
145
+ requiredLayoutElements.forEach(requiredLayoutElement => {
146
+ if (!requiredLayoutElement.trim()) return;
147
+ if (excludedLayouts.includes(requiredLayoutElement)) return;
148
+ const options: TimePickerLayoutElementBuilderOptions = {
149
+ formattedDate,
150
+ scheme: this.props.scheme,
151
+ layoutElement: requiredLayoutElement,
152
+ text: this.labelsMap[requiredLayoutElement],
153
+ action: controlActionMap[requiredLayoutElement],
154
+ control: controlPropsMap[requiredLayoutElement],
155
+ basicAttrs: this.props.attrsRelay[requiredLayoutElement],
156
+ };
157
+ if (requiredLayoutElement === DateTimePickerLayoutElement.WeekdaysElements) {
158
+ layoutElements[DateTimePickerLayoutElement.WeekdaysElements] = (<div className={Classname.build("noseur-date-time-picker-weekdays", this.props.attrsRelay?.weekdays?.className)}>
159
+ {this.props.weekdays.map((weekDay) => {
160
+ const opts = {
161
+ ...options,
162
+ layoutElement: weekDay,
163
+ text: DateHelper.translateWeekday(weekDay, this.props.locale),
164
+ control: controlPropsMap[DateTimePickerLayoutElement.WeekDayElement],
165
+ basicAttrs: addClassesToComponentElementBasicAttributes(this.props.attrsRelay[weekDay], Classname.build("noseur-date-time-picker-weekdays-day", this.props.attrsRelay?.weekdays?.weekday?.className))
166
+ };
167
+ return (this.props.weekdayTemplate
168
+ ? this.props.weekdayTemplate(weekDay, {
169
+ options: opts,
170
+ formattedDate,
171
+ controlActionMap,
172
+ props: this.props,
173
+ labelsMap: this.labelsMap,
174
+ elementBuilder: dateTimePickerBuildLayoutElement,
175
+ layoutElement: DateTimePickerLayoutElement.WeekDayElement,
176
+ })
177
+ : dateTimePickerBuildLayoutElement(opts));
178
+ })}
179
+ </div>);
180
+ return;
181
+ } else if (requiredLayoutElement === DateTimePickerLayoutElement.SelectedDatesElements) {
182
+ layoutElements[DateTimePickerLayoutElement.SelectedDatesElements] = (<React.Fragment>
183
+ {this.state.selectedDates.map((date) => {
184
+ const opts = {
185
+ ...options,
186
+ layoutElement: DateTimePickerLayoutElement.SelectedDateElement,
187
+ text: date.toLocaleString(this.props.locale, this.props.dateFormat),
188
+ control: controlPropsMap[DateTimePickerLayoutElement.SelectedDateElement],
189
+ basicAttrs: addClassesToComponentElementBasicAttributes(this.props.attrsRelay[DateTimePickerLayoutElement.SelectedDateElement], Classname.build("noseur-date-time-picker-selected-dates-selected-date", this.props.attrsRelay?.selectedDate?.className))
190
+ };
191
+ return (this.props.selectedDateTemplate
192
+ ? this.props.selectedDateTemplate(date, {
193
+ options: opts,
194
+ formattedDate,
195
+ controlActionMap,
196
+ props: this.props,
197
+ labelsMap: this.labelsMap,
198
+ elementBuilder: dateTimePickerBuildLayoutElement,
199
+ layoutElement: DateTimePickerLayoutElement.SelectedDateElement,
200
+ })
201
+ : dateTimePickerBuildLayoutElement(opts));
202
+ })}
203
+ </React.Fragment>);
204
+ return;
205
+ } else if (requiredLayoutElement === DateTimePickerLayoutElement.DaysElements) {
206
+ const daysElements: any[] = [];
207
+ const row = 7, column = 6, rowColumnSum = row * column;
208
+ const underline = this.props.showDatesSeparator && !this.props.showGridLines;
209
+ const monthDays = DateHelper.getAllDaysInMonth(formattedDate.year, formattedDate.month);
210
+ const startWeekday = monthDays[0].getDay();
211
+ const previousMonthPadding = startWeekday;
212
+ const nextMonthPadding = rowColumnSum - (monthDays.length + previousMonthPadding);
213
+ const previousMonthDays = previousMonthPadding === 0 ? [] : this.props.dontOverlapDate
214
+ ? Array(previousMonthPadding).fill(" ")
215
+ : DateHelper.getAllDaysInMonth(formattedDate.year, formattedDate.month - 1, previousMonthPadding, true);
216
+ const nextMonthDays = this.props.dontOverlapDate
217
+ ? Array(nextMonthPadding).fill(" ")
218
+ : DateHelper.getAllDaysInMonth(formattedDate.year, formattedDate.month + 1, nextMonthPadding);
219
+ previousMonthDays.forEach(day => daysElements.push(this.buildDateElement(day, controlPropsMap[DateTimePickerLayoutElement.DayElement], controlActionMap)));
220
+ monthDays.forEach(day => daysElements.push(this.buildDateElement(day, controlPropsMap[DateTimePickerLayoutElement.DayElement], controlActionMap)));
221
+ nextMonthDays.forEach(day => daysElements.push(this.buildDateElement(day, controlPropsMap[DateTimePickerLayoutElement.DayElement], controlActionMap)));
222
+ const className = Classname.build("noseur-date-time-picker-days", this.props.attrsRelay?.days?.className, {
223
+ "noseur-date-time-picker-days-underline": underline,
224
+ }, (underline ? this.props.attrsRelay?.days?.underline?.className : null));
225
+ layoutElements[DateTimePickerLayoutElement.DaysElements] = (<div className={className} style={{ gridTemplateColumns: this.props.weekdays.map(_ => "auto").join(" ") }}>
226
+ {daysElements}
227
+ </div>);
228
+ return;
229
+ } else if (requiredLayoutElement === DateTimePickerLayoutElement.YearsElements) {
230
+ const comparatorYear = this.props.mode === DateTimePickerMode.DATETIME ? activeYear : selectedYear;
231
+ layoutElements[DateTimePickerLayoutElement.YearsElements] = (<div className={Classname.build("noseur-date-time-picker-years", this.props.attrsRelay?.years?.className)}>
232
+ {Array(this.props.modeDifferenceCount).fill(undefined).map((_, index) => {
233
+ const year = activeYear + index;
234
+ const action = (event: Event) => this.onSelectYear(event, year);
235
+ const className = Classname.build("noseur-date-time-picker-long-year", this.props.attrsRelay?.years?.year?.className);
236
+ if (comparatorYear === year) controlPropsMap[DateTimePickerLayoutElement.YearElement] = {
237
+ className: Classname.build(className, "noseur-date-time-picker-long-year-selected", this.props.attrsRelay?.years?.selected?.className)
238
+ }; else controlPropsMap[DateTimePickerLayoutElement.YearElement] = { className };
239
+ const opts = {
240
+ ...options,
241
+ action,
242
+ text: year,
243
+ layoutElement: DateTimePickerLayoutElement.YearElement,
244
+ control: controlPropsMap[DateTimePickerLayoutElement.YearElement],
245
+ basicAttrs: addClassesToComponentElementBasicAttributes(this.props.attrsRelay[DateTimePickerLayoutElement.YearElement], Classname.build((controlPropsMap[DateTimePickerLayoutElement.YearElement] || {}).className))
246
+ };
247
+
248
+ return (this.props.yearTemplate
249
+ ? this.props.yearTemplate(index, {
250
+ options: opts,
251
+ formattedDate,
252
+ controlActionMap,
253
+ props: this.props,
254
+ labelsMap: this.labelsMap,
255
+ elementBuilder: dateTimePickerBuildLayoutElement,
256
+ layoutElement: DateTimePickerLayoutElement.YearElement,
257
+ })
258
+ : dateTimePickerBuildLayoutElement(opts));
259
+ })}
260
+ </div>);
261
+ return;
262
+ } else if (requiredLayoutElement === DateTimePickerLayoutElement.MonthsElements) {
263
+ const activeSelectedDate = DateHelper.clone(this.state.selectedDates.length ? this.state.selectedDates[0] : new Date());
264
+ layoutElements[DateTimePickerLayoutElement.MonthsElements] = (<div className="noseur-date-time-picker-months">
265
+ {Array(12).fill(undefined).map((_, index) => {
266
+ const selectedDate = DateHelper.clone(activeSelectedDate); selectedDate.setMonth(index);
267
+ const action = (event: Event) => this.onSelectMonth(event, index, activeYear);
268
+ const className = Classname.build("noseur-date-time-picker-month-name", this.props.attrsRelay?.years?.year?.className);
269
+ if (activeSelectedDate.getMonth() === index && activeSelectedDate.getFullYear() === activeYear) controlPropsMap[DateTimePickerLayoutElement.MonthElement] = {
270
+ className: Classname.build(className, "noseur-date-time-picker-month-name-selected", this.props.attrsRelay?.years?.selected?.className)
271
+ }; else controlPropsMap[DateTimePickerLayoutElement.MonthElement] = { className };
272
+ const monthName = selectedDate.toLocaleString(this.props.locale, { month: 'short' });
273
+ const opts = {
274
+ ...options,
275
+ action,
276
+ text: monthName,
277
+ layoutElement: DateTimePickerLayoutElement.MonthElement,
278
+ control: controlPropsMap[DateTimePickerLayoutElement.MonthElement],
279
+ basicAttrs: addClassesToComponentElementBasicAttributes(this.props.attrsRelay[DateTimePickerLayoutElement.MonthElement], Classname.build((controlPropsMap[DateTimePickerLayoutElement.MonthElement] || {}).className))
280
+ };
281
+
282
+ return (this.props.monthTemplate
283
+ ? this.props.monthTemplate(MonthIndex[index], {
284
+ options: opts,
285
+ formattedDate,
286
+ controlActionMap,
287
+ props: this.props,
288
+ labelsMap: this.labelsMap,
289
+ elementBuilder: dateTimePickerBuildLayoutElement,
290
+ layoutElement: DateTimePickerLayoutElement.YearElement,
291
+ })
292
+ : dateTimePickerBuildLayoutElement(opts));
293
+ })}
294
+ </div>);
295
+ return;
296
+ }
297
+ options.scheme = this.selectDateControlScheme(requiredLayoutElement);
298
+ if (!DateTimePickerLayoutElementsValues.includes(requiredLayoutElement) && this.props.customElementTemplate) {
299
+ const opts = {
300
+ ...options,
301
+ basicAttrs: addClassesToComponentElementBasicAttributes(this.props.attrsRelay[DateTimePickerLayoutElement.MonthElement], "noseur-date-time-picker-custom")
302
+ };
303
+ layoutElements[requiredLayoutElement] = this.props.customElementTemplate({
304
+ options: opts,
305
+ formattedDate,
306
+ controlActionMap,
307
+ props: this.props,
308
+ labelsMap: this.labelsMap,
309
+ layoutElement: requiredLayoutElement,
310
+ elementBuilder: dateTimePickerBuildLayoutElement,
311
+ });
312
+ return;
313
+ }
314
+ if (requiredLayoutElement === DateTimePickerLayoutElement.YearToElement) options.text = `` + (activeYear + this.props.modeDifferenceCount - 1);
315
+ layoutElements[requiredLayoutElement] = dateTimePickerBuildLayoutElement(options);
316
+ });
317
+ requiredLayoutElements.forEach(requiredLayoutElement => {
318
+ const options = {
319
+ formattedDate,
320
+ scheme: this.props.scheme,
321
+ layoutElement: requiredLayoutElement,
322
+ text: this.labelsMap[requiredLayoutElement],
323
+ action: controlActionMap[requiredLayoutElement],
324
+ control: controlPropsMap[requiredLayoutElement],
325
+ basicAttrs: this.props.attrsRelay[requiredLayoutElement],
326
+ };
327
+ if (!requiredLayoutElement.includes("Element") || !excludedLayouts.includes(requiredLayoutElement)) return;
328
+ if (requiredLayoutElement === DateTimePickerLayoutElement.HeaderElement && !this.props.timeOnly) {
329
+ const className = Classname.build("noseur-date-time-picker-header");
330
+ layoutElements[DateTimePickerLayoutElement.HeaderElement] = this.buildLayoutElement(options, formattedDate, layoutElements, DateTimePickerLayoutElement.HeaderElement, this.props.headerLayout, className, this.props.headerTemplate, controlActionMap);
331
+ } else if (requiredLayoutElement === DateTimePickerLayoutElement.FooterElement && !this.props.timeOnly) {
332
+ const className = Classname.build("noseur-date-time-picker-footer");
333
+ layoutElements[DateTimePickerLayoutElement.FooterElement] = this.buildLayoutElement(options, formattedDate, layoutElements, DateTimePickerLayoutElement.FooterElement, this.props.footerLayout, className, this.props.footerTemplate, controlActionMap);
334
+ } else if (requiredLayoutElement === DateTimePickerLayoutElement.YearModeHeaderElement && !this.props.timeOnly) {
335
+ const className = Classname.build("noseur-date-time-picker-year-mode-header");
336
+ layoutElements[DateTimePickerLayoutElement.YearModeHeaderElement] = this.buildLayoutElement(options, formattedDate, layoutElements, DateTimePickerLayoutElement.YearModeHeaderElement, this.props.yearModeHeaderLayout, className, this.props.yearModeHeaderTemplate, controlActionMap);
337
+ } else if (requiredLayoutElement === DateTimePickerLayoutElement.YearModeFooterElement && !this.props.timeOnly) {
338
+ const className = Classname.build("noseur-date-time-picker-year-mode-footer");
339
+ layoutElements[DateTimePickerLayoutElement.YearModeFooterElement] = this.buildLayoutElement(options, formattedDate, layoutElements, DateTimePickerLayoutElement.YearModeFooterElement, this.props.yearModeFooterLayout, className, this.props.yearModeFooterTemplate, controlActionMap);
340
+ } else if (requiredLayoutElement === DateTimePickerLayoutElement.MonthModeHeaderElement && !this.props.timeOnly) {
341
+ const className = Classname.build("noseur-date-time-picker-month-mode-header");
342
+ layoutElements[DateTimePickerLayoutElement.MonthModeHeaderElement] = this.buildLayoutElement(options, formattedDate, layoutElements, DateTimePickerLayoutElement.MonthModeHeaderElement, this.props.monthModeHeaderLayout, className, this.props.monthModeHeaderTemplate, controlActionMap);
343
+ } else if (requiredLayoutElement === DateTimePickerLayoutElement.MonthModeFooterElement && !this.props.timeOnly) {
344
+ const className = Classname.build("noseur-date-time-picker-month-mode-footer");
345
+ layoutElements[DateTimePickerLayoutElement.MonthModeFooterElement] = this.buildLayoutElement(options, formattedDate, layoutElements, DateTimePickerLayoutElement.MonthModeFooterElement, this.props.monthModeFooterLayout, className, this.props.monthModeFooterTemplate, controlActionMap);
346
+ } else if (requiredLayoutElement === DateTimePickerLayoutElement.TopPanelElement && !this.props.timeOnly) {
347
+ const className = Classname.build("noseur-date-time-picker-top-panel");
348
+ layoutElements[DateTimePickerLayoutElement.TopPanelElement] = this.buildLayoutElement(options, formattedDate, layoutElements, DateTimePickerLayoutElement.TopPanelElement, this.props.topLayout, className, this.props.topPanelTemplate, controlActionMap);
349
+ } else if (requiredLayoutElement === DateTimePickerLayoutElement.BottomPanelElement && !this.props.timeOnly) {
350
+ const className = Classname.build("noseur-date-time-picker-bottom-panel");
351
+ layoutElements[DateTimePickerLayoutElement.BottomPanelElement] = this.buildLayoutElement(options, formattedDate, layoutElements, DateTimePickerLayoutElement.BottomPanelElement, this.props.bottomLayout, className, this.props.bottomPanelTemplate, controlActionMap);
352
+ } else if (requiredLayoutElement === DateTimePickerLayoutElement.LeftPanelElement && !this.props.timeOnly) {
353
+ const className = Classname.build("noseur-date-time-picker-left-panel");
354
+ layoutElements[DateTimePickerLayoutElement.LeftPanelElement] = this.buildLayoutElement(options, formattedDate, layoutElements, DateTimePickerLayoutElement.LeftPanelElement, this.props.leftLayout, className, this.props.leftPanelTemplate, controlActionMap);
355
+ } else if (requiredLayoutElement === DateTimePickerLayoutElement.RightPanelElement && !this.props.timeOnly) {
356
+ const className = Classname.build("noseur-date-time-picker-right-panel");
357
+ layoutElements[DateTimePickerLayoutElement.RightPanelElement] = this.buildLayoutElement(options, formattedDate, layoutElements, DateTimePickerLayoutElement.RightPanelElement, this.props.rightLayout, className, this.props.rightPanelTemplate, controlActionMap);
358
+ } else if (requiredLayoutElement === DateTimePickerLayoutElement.SelectionElement && !this.props.timeOnly) {
359
+ const className = Classname.build("noseur-date-time-picker-selection");
360
+ const selectionTemplate = !this.props.selectionTemplate ? null : (options: DateTimePickerElementOptions) => this.props.selectionTemplate(this.state.selectedDates, options);
361
+ layoutElements[DateTimePickerLayoutElement.SelectionElement] = this.buildLayoutElement(options, formattedDate, layoutElements, DateTimePickerLayoutElement.SelectionElement, this.props.selectionLayout, className, selectionTemplate, controlActionMap);
362
+ } else if (requiredLayoutElement === DateTimePickerLayoutElement.TimeElement && this.props.showTime) {
363
+ const className = Classname.build("noseur-date-time-picker-time");
364
+ layoutElements[DateTimePickerLayoutElement.TimeElement] = this.buildLayoutElement(options, formattedDate, layoutElements, DateTimePickerLayoutElement.TimeElement, this.props.timeLayout, className, this.props.timeTemplate, controlActionMap);
365
+ }
366
+ });
367
+ return layoutElements;
368
+ }*/
369
+ // TODO able to support multiple colors with each dot on slider map and on the pallete
370
+ buildLayout(/*layoutElements: NoseurObject<NoseurElement>, controlActionMap*/ _) {
371
+ const selectedColor = this.state.selectedColors?.[0];
372
+ return (React.createElement("div", { style: { display: "flex", width: "fit-content", flexDirection: "column" } },
373
+ React.createElement(ColorMap, { style: { width: "100%" }, mapWidth: "100%", mapHeight: 150, hex: selectedColor?.hex }),
374
+ React.createElement(ColorSlider, { style: { width: "100%", margin: "5px 0px" }, orientation: Orientation.HORIZONTAL, colorGradient: ColorSliderGradient.RAINBOW_HORIZONTAL, onSelectColor: async ({ color }) => {
375
+ color.alpha = this.state.alpha;
376
+ this.reportOnSelectColor(color);
377
+ } }),
378
+ React.createElement(ColorSlider, { style: { width: "100%", margin: "5px 0px" }, orientation: Orientation.HORIZONTAL, colorGradient: ColorSliderGradient.TRANSPARENT_HORIZONTAL, primaryColor: selectedColor.hex, onSelectColor: async ({ color }) => {
379
+ this.reportOnSelectColor({ ...this.state.selectedColors?.[0], alpha: color.alpha });
380
+ } }),
381
+ React.createElement("div", { style: { display: "flex", width: "100%", marginTop: 5 } },
382
+ React.createElement(FormControl, { isFieldset: true, label: React.createElement("span", { style: { fontSize: 12 } }, "Hex") },
383
+ React.createElement(TextInput, { style: { flex: 1, width: 60, padding: "7px 5px", fontSize: 14 }, defaultValue: selectedColor.hex })),
384
+ React.createElement(FormControl, { isFieldset: true, label: React.createElement("span", { style: { fontSize: 12 } }, "R") },
385
+ React.createElement(TextInput, { style: { width: 40, padding: "7px 5px", fontSize: 14 }, defaultValue: "200" })),
386
+ React.createElement(FormControl, { isFieldset: true, label: React.createElement("span", { style: { fontSize: 12 } }, "G") },
387
+ React.createElement(TextInput, { style: { width: 40, padding: "7px 5px", fontSize: 14 }, defaultValue: "200" })),
388
+ React.createElement(FormControl, { isFieldset: true, label: React.createElement("span", { style: { fontSize: 12 } }, "B") },
389
+ React.createElement(TextInput, { style: { width: 40, padding: "7px 5px", fontSize: 14 }, defaultValue: "200" })),
390
+ React.createElement(FormControl, { isFieldset: true, label: React.createElement("span", { style: { fontSize: 12 } }, "A") },
391
+ React.createElement(TextInput, { style: { width: 40, padding: "7px 5px", fontSize: 14 }, defaultValue: "100" }))),
392
+ React.createElement(ColorPalette, { style: { width: "100%", marginTop: 10 }, grid: 10, gtcSize: "1fr", row: 4, size: 20, gap: 3, palette: "Default", attrsRelay: { tile: { style: { borderRadius: 2 } } }, onSelectColor: ({ color }) => {
393
+ color.alpha = this.state.alpha;
394
+ this.reportOnSelectColor(color);
395
+ } })));
396
+ /*let layout = this.props.layout;
397
+ if (this.state.activeMode === DateTimePickerMode.YEAR) layout = this.props.yearModeLayout;
398
+ if (this.state.activeMode === DateTimePickerMode.MONTH) layout = this.props.monthModeLayout;
399
+ const rows = layout.split(DateTimePickerLayoutElement.RowDividerElement);
400
+ return rows.map((row, index) => {
401
+ if (!row.trim()) return null;
402
+ const className = Classname.build("noseur-date-time-picker-layout noseur-date-time-picker-layout-row");
403
+ const columns = row.split(DateTimePickerLayoutElement.ColumnDividerElement);
404
+ return (<div className={className} key={index}>
405
+ {columns.map((column, index) => {
406
+ const className = Classname.build("noseur-date-time-picker-layout noseur-date-time-picker-layout-column", {
407
+ "noseur-wd-100-pct": BoolHelper.equalsAny(column.trim(), ["TopPanelElement", "BottomPanelElement"])
408
+ });
409
+ const options = {
410
+ formattedDate,
411
+ layoutElement: column,
412
+ scheme: this.props.scheme,
413
+ text: this.labelsMap[column],
414
+ action: controlActionMap[column],
415
+ basicAttrs: addClassesToComponentElementBasicAttributes(this.props.attrsRelay[column], "noseur-date-time-picker-custom"),
416
+ };
417
+ return this.buildLayoutElement(options, formattedDate, layoutElements, DateTimePickerLayoutElement.MainLayoutElement, column, className, this.props.layoutTemplate, controlActionMap, index);
418
+ })}
419
+ </div>);
420
+ });*/
421
+ }
422
+ render() {
423
+ const controlActionMap = {
424
+ MapToggleElement: this.toggleMapComponent,
425
+ PalleteToggleElement: this.togglePalleteElement,
426
+ //SelectColor: (e) => { this.reportOnSelectColor(); this.toggle(e); },
427
+ ClearElement: () => this.performColorControlAction(ColorPickerLayoutElement.ClearElement),
428
+ CancelElement: () => this.performColorControlAction(ColorPickerLayoutElement.CancelElement),
429
+ ChooseElement: () => this.performColorControlAction(ColorPickerLayoutElement.ChooseElement),
430
+ ClearSolidColorElement: () => this.performColorControlAction(ColorPickerLayoutElement.ClearSolidColorElement),
431
+ ColorFormatDropdownElement: () => this.performColorControlAction(ColorPickerLayoutElement.ColorFormatDropdownElement),
432
+ ClearTransparentColorElement: () => this.performColorControlAction(ColorPickerLayoutElement.ClearTransparentColorElement),
433
+ };
434
+ //const layoutElements = this.buildLayoutElements(controlActionMap);
435
+ const layoutPanel = this.buildLayout(/*layoutElements, */ controlActionMap);
436
+ const className = Classname.build("noseur-color-picker", {
437
+ "noseur-color-picker-modal": this.props.type === ComponentRenderType.MODAL,
438
+ "noseur-color-picker-inline": this.props.type === ComponentRenderType.INLINE,
439
+ "noseur-color-picker-popover": this.props.type === ComponentRenderType.POPOVER,
440
+ }, this.props.scheme ? `${this.props.scheme}-vars` : null, this.props.className);
441
+ const ref = (r) => {
442
+ if (!r)
443
+ return;
444
+ if (this.props.autoFocus)
445
+ r.focus();
446
+ ObjectHelper.resolveRef(this.props.forwardRef, r);
447
+ };
448
+ switch (this.props.type) {
449
+ case ComponentRenderType.MODAL:
450
+ return (React.createElement(Dialog, { notClosable: false, ...this.props.attrsRelay?.dialog, ref: ref, className: className, style: this.props.style, manageRef: (m) => this.dialogManageRef = m, visible: this.state.modalVisible, onHide: () => this.setState({ modalVisible: false }) }, layoutPanel));
451
+ case ComponentRenderType.POPOVER:
452
+ return (React.createElement(Popover, { outsideClickLogic: "positional", ...this.props.attrsRelay?.popover, ref: ref, className: className, style: this.props.style, manageRef: (m) => this.popoverManageRef = m }, layoutPanel));
453
+ default:
454
+ return (React.createElement("div", { ref: ref, className: className, style: this.props.style }, layoutPanel));
455
+ }
456
+ }
457
+ ;
84
458
  }
85
459
  export const ColorPicker = ({ ref, ...props }) => (React.createElement(ColorPickerComponent, { ...props, forwardRef: ref }));
460
+ // https://alabsi91.github.io/reanimated-color-picker/
@@ -18,5 +18,7 @@ export interface ColorMapProps extends ComponentBaseProps<HTMLDivElement, ColorM
18
18
  alignAlpha: Alignment;
19
19
  alignSlider: Alignment;
20
20
  indicator: NoseurElement;
21
+ mapWidth: number | string;
22
+ mapHeight: number | string;
21
23
  }
22
24
  export declare const ColorMap: ({ ref, ...props }: Partial<ColorMapProps>) => React.JSX.Element;
@@ -2,6 +2,8 @@ import React from "react";
2
2
  import { Classname } from "../utils/Classname";
3
3
  class ColorMapComponent extends React.Component {
4
4
  static defaultProps = {
5
+ mapWidth: 180,
6
+ mapHeight: 180,
5
7
  hex: "#000000",
6
8
  };
7
9
  state = {
@@ -22,8 +24,8 @@ class ColorMapComponent extends React.Component {
22
24
  return;
23
25
  const className = Classname.build("noseur-color-map-map", this.props.attrsRelay?.map?.className);
24
26
  const style = {
25
- width: this.props.attrsRelay?.map?.size ?? 180,
26
- height: this.props.attrsRelay?.map?.size ?? 180,
27
+ width: this.props.attrsRelay?.map?.size ?? this.props.mapWidth,
28
+ height: this.props.attrsRelay?.map?.size ?? this.props.mapHeight,
27
29
  ...(this.props.attrsRelay?.map?.style ?? {}),
28
30
  backgroundColor: this.state.hex,
29
31
  };
@@ -5,8 +5,10 @@ export type ColorPaletteAttributesRelays = {
5
5
  tile?: ComponentElementBasicAttributes;
6
6
  };
7
7
  export interface ColorPaletteProps extends ComponentBaseProps<HTMLDivElement, {}, ColorPaletteAttributesRelays> {
8
+ row: number;
8
9
  grid: number;
9
10
  defaultValue: string;
11
+ gtcSize: number | string;
10
12
  palette: string[] | string;
11
13
  gap: number | {
12
14
  row: number;
@@ -34,16 +34,20 @@ class ColorPaletteComponent extends React.Component {
34
34
  return (React.createElement("div", { key: color, className: Classname.build("noseur-color-palette-tile", this.props.attrsRelay?.tile?.className, { "active": color === this.state.value }), style: style, onClick: () => this.onSelectColor(color) }));
35
35
  }
36
36
  render() {
37
- const width = (typeof this.props.size === "number" ? this.props.size : this.props.size.width);
37
+ let palette = this.state.palette;
38
+ const width = (!!this.props.gtcSize ? this.props.gtcSize : (typeof this.props.size === "number" ? this.props.size : this.props.size.width));
38
39
  const className = Classname.build("noseur-color-palette", this.props.className);
39
40
  const style = {
40
41
  ...(this.props.style ?? {}),
41
- gridTemplateColumns: Array(Math.min(this.state.palette.length, this.props.grid)).fill(`${width}px`).join(" "),
42
+ gridTemplateColumns: Array(Math.min(this.state.palette.length, this.props.grid)).fill(typeof width === "number" ? `${width}px` : width).join(" "),
42
43
  columnGap: (typeof this.props.gap !== "number" ? this.props.gap.column : undefined),
43
44
  rowGap: (typeof this.props.gap !== "number" ? this.props.gap.row : undefined),
44
45
  gap: (typeof this.props.gap === "number" ? this.props.gap : undefined),
45
46
  };
46
- return (React.createElement("div", { className: className, style: style, id: this.props.id, key: this.props.key }, this.state.palette.map((color) => this.renderTile(color))));
47
+ if (this.props.row) {
48
+ palette = palette.slice(0, (this.props.grid * this.props.row));
49
+ }
50
+ return (React.createElement("div", { className: className, style: style, id: this.props.id, key: this.props.key }, palette.map((color) => this.renderTile(color))));
47
51
  }
48
52
  ;
49
53
  }
@@ -0,0 +1,4 @@
1
+ export declare function useScreenDimension(): {
2
+ width: number;
3
+ height: number;
4
+ };
@@ -0,0 +1,25 @@
1
+ import React from "react";
2
+ import { ObserverHandler } from "../utils/DOMUtils";
3
+ export function useScreenDimension() {
4
+ let documentResizeListener;
5
+ const [screenDimension, setScreenDimension] = React.useState({ width: 0, height: 0 });
6
+ React.useEffect(() => {
7
+ if (!documentResizeListener) {
8
+ documentResizeListener = (_) => {
9
+ const width = document.documentElement.clientWidth;
10
+ const height = document.documentElement.clientHeight;
11
+ setScreenDimension({ width, height });
12
+ };
13
+ ObserverHandler.observe("resize", documentResizeListener);
14
+ }
15
+ return () => {
16
+ if (documentResizeListener) {
17
+ ObserverHandler.unobserve("resize", documentResizeListener);
18
+ documentResizeListener = undefined;
19
+ }
20
+ };
21
+ }, []);
22
+ return {
23
+ ...screenDimension
24
+ };
25
+ }
@@ -54,7 +54,9 @@ export * from "./panel/Accordion";
54
54
  export * from "./panel/ScrollPanel";
55
55
  export * from "./layout/GridView";
56
56
  export * from "./sensor/DragSensor";
57
+ export * from "./sensor/ResizeSensor";
57
58
  export * from "./sensor/ViewportSensor";
58
59
  export * from "./hooks/useSubscription";
59
60
  export * from "./hooks/useSearchParams";
61
+ export * from "./hooks/useScreenDimension";
60
62
  import "./core/noseur.css";
package/dist/esm/index.js CHANGED
@@ -66,8 +66,10 @@ export * from "./panel/ScrollPanel";
66
66
  export * from "./layout/GridView";
67
67
  // sensor
68
68
  export * from "./sensor/DragSensor";
69
+ export * from "./sensor/ResizeSensor";
69
70
  export * from "./sensor/ViewportSensor";
70
71
  // hooks
71
72
  export * from "./hooks/useSubscription";
72
73
  export * from "./hooks/useSearchParams";
74
+ export * from "./hooks/useScreenDimension";
73
75
  import "./core/noseur.css";
@@ -278,6 +278,7 @@
278
278
  .noseur-messages > div {
279
279
  z-index: 1005;
280
280
  display: flex;
281
+ width: max-content;
281
282
  flex-direction: column;
282
283
  }
283
284
 
@@ -177,7 +177,7 @@ class PopoverComponent extends React.Component {
177
177
  rePosition(event, cb) {
178
178
  if (!this.state.visible)
179
179
  return;
180
- this.target = event?.target ?? event?.currentTarget ?? this.target;
180
+ this.target = this.target ?? event?.target ?? event?.currentTarget ?? this.target;
181
181
  if (!this.target || !this.target.getBoundingClientRect)
182
182
  return;
183
183
  DOMHelper.absolutePositionRelatively(this.internalElement, this.target, this.props.positional);
@@ -0,0 +1,17 @@
1
+ import React from "react";
2
+ import { ComponentBaseProps } from "../core/ComponentBaseProps";
3
+ export interface ResizeDimension {
4
+ width: number;
5
+ height: number;
6
+ }
7
+ export type ResizeSensorRenderIfHandler = (clientWidth: number, clientHeight: number) => boolean;
8
+ export type ResizeSensorDimensionChangeHandler = (event: any, dimension: ResizeDimension) => void;
9
+ export interface ResizeSensorManageRef {
10
+ }
11
+ export interface ResizeSensorProps extends ComponentBaseProps<HTMLDivElement, ResizeSensorManageRef> {
12
+ minDimension: Partial<ResizeDimension>;
13
+ maxDimension: Partial<ResizeDimension>;
14
+ renderIf: ResizeSensorRenderIfHandler;
15
+ onDimensionChange: ResizeSensorDimensionChangeHandler;
16
+ }
17
+ export declare const ResizeSensor: ({ ref, ...props }: Partial<ResizeSensorProps>) => React.JSX.Element;
@@ -0,0 +1,71 @@
1
+ import React from "react";
2
+ import { ObjectHelper } from "../utils/ObjectHelper";
3
+ import { ObserverHandler } from "../utils/DOMUtils";
4
+ class ResizeSensorComponent extends React.Component {
5
+ static defaultProps = {};
6
+ state = {
7
+ renderChildren: this.shouldRenderChildren(this.props.minDimension, this.props.maxDimension, document.documentElement.clientWidth, document.documentElement.clientHeight),
8
+ };
9
+ documentResizeListener;
10
+ constructor(props) {
11
+ super(props);
12
+ }
13
+ componentDidMount() {
14
+ if (!this.documentResizeListener) {
15
+ this.documentResizeListener = (event) => {
16
+ const width = document.documentElement.clientWidth;
17
+ const height = document.documentElement.clientHeight;
18
+ this.props.onDimensionChange?.(event, { width: width, height: height });
19
+ this.setState({ renderChildren: this.shouldRenderChildren(this.props.minDimension, this.props.maxDimension, width, height) });
20
+ };
21
+ ObserverHandler.observe("resize", this.documentResizeListener);
22
+ }
23
+ }
24
+ componentWillUnmount() {
25
+ if (this.documentResizeListener) {
26
+ ObserverHandler.unobserve("resize", this.documentResizeListener);
27
+ this.documentResizeListener = undefined;
28
+ }
29
+ }
30
+ shouldRenderChildren(minDimension, maxDimension, screenWidth, screenHeight) {
31
+ if (this.props.renderIf?.(screenWidth, screenHeight))
32
+ return true;
33
+ if (!minDimension && !maxDimension) {
34
+ return true;
35
+ }
36
+ if (minDimension) {
37
+ if (minDimension.width !== undefined && minDimension.height !== undefined && minDimension.width < screenWidth && minDimension.height < screenHeight) {
38
+ return true;
39
+ }
40
+ else if (minDimension.width !== undefined && minDimension.width < screenWidth) {
41
+ return true;
42
+ }
43
+ else if (minDimension.height !== undefined && minDimension.height < screenHeight) {
44
+ return true;
45
+ }
46
+ }
47
+ else if (maxDimension) {
48
+ if (maxDimension.width !== undefined && maxDimension.height !== undefined && maxDimension.width > screenWidth && maxDimension.height > screenHeight) {
49
+ return true;
50
+ }
51
+ else if (maxDimension.width !== undefined && maxDimension.width > screenWidth) {
52
+ return true;
53
+ }
54
+ else if (maxDimension.height !== undefined && maxDimension.height > screenHeight) {
55
+ return true;
56
+ }
57
+ }
58
+ return false;
59
+ }
60
+ render() {
61
+ let childrenProps = ObjectHelper.conditionalClone(this.props, (key) => key in [...Object.keys(this.props), "children"]);
62
+ const children = !this.state.renderChildren ? null : React.Children.map(this.props.children, (child) => {
63
+ if (React.isValidElement(child)) {
64
+ return React.cloneElement(child, { ...(child.props ?? {}), ...childrenProps });
65
+ }
66
+ return child;
67
+ });
68
+ return (React.createElement(React.Fragment, { key: this.props.key }, (this.state.renderChildren) ? children : null));
69
+ }
70
+ }
71
+ export const ResizeSensor = ({ ref, ...props }) => (React.createElement(ResizeSensorComponent, { ...props, forwardRef: ref }));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rivtn/noseur",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Eccentric, managed and configurable react components",
5
5
  "main": "./dist/cjs/index.js",
6
6
  "module": "./dist/esm/index.js",