diff --git a/ipywidgets/widgets/trait_types.py b/ipywidgets/widgets/trait_types.py index b89ec13c93..f1a453457c 100644 --- a/ipywidgets/widgets/trait_types.py +++ b/ipywidgets/widgets/trait_types.py @@ -121,6 +121,54 @@ def datetime_from_json(js, manager): } +def naive_to_json(pydt, manager): + """Serialize a naive Python datetime object to json. + + Instantiating a JavaScript Date object with a string assumes that the + string is a UTC string, while instantiating it with constructor arguments + assumes that it's in local time: + + >>> cdate = new Date('2015-05-12') + Mon May 11 2015 20:00:00 GMT-0400 (Eastern Daylight Time) + >>> cdate = new Date(2015, 4, 12) // Months are 0-based indices in JS + Tue May 12 2015 00:00:00 GMT-0400 (Eastern Daylight Time) + + Attributes of this dictionary are to be passed to the JavaScript Date + constructor. + """ + if pydt is None: + return None + else: + naivedt = pydt.replace(tzinfo=None) + return dict( + year=naivedt.year, + month=naivedt.month - 1, # Months are 0-based indices in JS + date=naivedt.day, + hours=naivedt.hour, # Hours, Minutes, Seconds and Milliseconds + minutes=naivedt.minute, # are plural in JS + seconds=naivedt.second, + milliseconds=naivedt.microsecond / 1000, + ) + + +def naive_from_json(js, manager): + """Deserialize a naive Python datetime object from json.""" + if js is None: + return None + else: + return dt.datetime( + js["year"], + js["month"] + 1, # Months are 1-based in Python + js["date"], + js["hours"], + js["minutes"], + js["seconds"], + js["milliseconds"] * 1000, + ) + +naive_serialization = {"from_json": naive_from_json, "to_json": naive_to_json} + + def date_to_json(pydate, manager): """Serialize a Python date object. diff --git a/ipywidgets/widgets/widget_datetime.py b/ipywidgets/widgets/widget_datetime.py index 12e450de73..0a1ccab6ac 100644 --- a/ipywidgets/widgets/widget_datetime.py +++ b/ipywidgets/widgets/widget_datetime.py @@ -10,7 +10,7 @@ from traitlets import Unicode, Bool, validate, TraitError -from .trait_types import datetime_serialization, Datetime +from .trait_types import datetime_serialization, Datetime, naive_serialization from .valuewidget import ValueWidget from .widget import register from .widget_core import CoreWidget @@ -20,7 +20,7 @@ @register class DatetimePicker(DescriptionWidget, ValueWidget, CoreWidget): """ - Display a widget for picking times. + Display a widget for picking datetimes. Parameters ---------- @@ -42,7 +42,7 @@ class DatetimePicker(DescriptionWidget, ValueWidget, CoreWidget): >>> import datetime >>> import ipydatetime - >>> datetime_pick = ipydatetime.TimePicker() + >>> datetime_pick = ipydatetime.DatetimePicker() >>> datetime_pick.value = datetime.datetime(2018, 09, 5, 12, 34, 3) """ @@ -55,10 +55,16 @@ class DatetimePicker(DescriptionWidget, ValueWidget, CoreWidget): min = Datetime(None, allow_none=True).tag(sync=True, **datetime_serialization) max = Datetime(None, allow_none=True).tag(sync=True, **datetime_serialization) + def _validate_tz(self, value): + if value.tzinfo is None: + raise TraitError('%s values needs to be timezone aware' % (self.__class__.__name__,)) + return value + @validate("value") def _validate_value(self, proposal): """Cap and floor value""" value = proposal["value"] + value = self._validate_tz(value) if self.min and self.min > value: value = max(value, self.min) if self.max and self.max < value: @@ -69,6 +75,7 @@ def _validate_value(self, proposal): def _validate_min(self, proposal): """Enforce min <= value <= max""" min = proposal["value"] + min = self._validate_tz(min) if self.max and min > self.max: raise TraitError("Setting min > max") if self.value and min > self.value: @@ -79,8 +86,53 @@ def _validate_min(self, proposal): def _validate_max(self, proposal): """Enforce min <= value <= max""" max = proposal["value"] + max = self._validate_tz(max) if self.min and max < self.min: raise TraitError("setting max < min") if self.value and max < self.value: self.value = max return max + + +@register +class NaiveDatetimePicker(DatetimePicker): + """ + Display a widget for picking naive datetimes (i.e. timezone unaware). + + Parameters + ---------- + + value: datetime.datetime + The current value of the widget. + + disabled: bool + Whether to disable user changes. + + min: datetime.datetime + The lower allowed datetime bound + + max: datetime.datetime + The upper allowed datetime bound + + Examples + -------- + + >>> import datetime + >>> import ipydatetime + >>> datetime_pick = ipydatetime.NaiveDatetimePicker() + >>> datetime_pick.value = datetime.datetime(2018, 09, 5, 12, 34, 3) + """ + + # Replace the serializers and model names: + + _model_name = Unicode("NaiveDatetimeModel").tag(sync=True) + + value = Datetime(None, allow_none=True).tag(sync=True, **naive_serialization) + + min = Datetime(None, allow_none=True).tag(sync=True, **naive_serialization) + max = Datetime(None, allow_none=True).tag(sync=True, **naive_serialization) + + def _validate_tz(self, value): + if value.tzinfo is not None: + raise TraitError('%s values needs to be timezone unaware' % (self.__class__.__name__,)) + return value diff --git a/packages/controls/src/widget_datetime.ts b/packages/controls/src/widget_datetime.ts index a422c0d40a..9fc43f8aa2 100644 --- a/packages/controls/src/widget_datetime.ts +++ b/packages/controls/src/widget_datetime.ts @@ -305,3 +305,94 @@ namespace Private { return value ? dt_as_dt_string(value).split('T', 2)[1] : ''; } } + +export interface ISerializedNaiveDatetime { + /** + * full year + */ + year: number; + + /** + * zero-based month (0 means January, 11 means December) + */ + month: number; + + /** + * day of month + */ + date: number; + + /** + * hour (24H format) + */ + hours: number; + + /** + * minutes + */ + minutes: number; + + /** + * seconds + */ + seconds: number; + + /** + * millisconds + */ + milliseconds: number; +} + +export function serialize_naive( + value: Date | null +): ISerializedNaiveDatetime | null { + if (value === null) { + return null; + } else { + return { + year: value.getFullYear(), + month: value.getMonth(), + date: value.getDate(), + hours: value.getHours(), + minutes: value.getMinutes(), + seconds: value.getSeconds(), + milliseconds: value.getMilliseconds() + }; + } +} + +export function deserialize_naive( + value: ISerializedNaiveDatetime +): Date | null { + if (value === null) { + return null; + } else { + const date = new Date(); + date.setFullYear(value.year, value.month, value.date); + date.setHours( + value.hours, + value.minutes, + value.seconds, + value.milliseconds + ); + return date; + } +} + +export const naive_serializers = { + serialize: serialize_naive, + deserialize: deserialize_naive +}; + +export class NaiveDatetimeModel extends DatetimeModel { + defaults(): Backbone.ObjectHash { + return { ...super.defaults(), _model_name: 'NaiveDatetimeModel' }; + } + + static serializers: ISerializers = { + ...CoreDescriptionModel.serializers, + value: naive_serializers, + min: naive_serializers, + max: naive_serializers + }; +} diff --git a/packages/controls/test/src/widget_datetime_test.ts b/packages/controls/test/src/widget_datetime_test.ts index b3864cd050..607567889e 100644 --- a/packages/controls/test/src/widget_datetime_test.ts +++ b/packages/controls/test/src/widget_datetime_test.ts @@ -11,7 +11,7 @@ import { createTestModelFromSerialized } from './utils'; -import { DatetimeModel, DatetimeView } from '../../lib'; +import { DatetimeModel, DatetimeView, NaiveDatetimeModel } from '../../lib'; describe('Datetime', () => { const date = new Date(); @@ -112,4 +112,89 @@ describe('Datetime', () => { expect(view.model).to.equal(model); }); }); + + describe('NaiveDatetimeModel', () => { + it('should be createable', () => { + const model = createTestModel(NaiveDatetimeModel); + expect(model).to.be.an.instanceof(NaiveDatetimeModel); + expect(model.get('value')).to.be.a('null'); + }); + + it('should be createable with a value', () => { + const state = { value: date }; + const model = createTestModel(NaiveDatetimeModel, state); + expect(model).to.be.an.instanceof(NaiveDatetimeModel); + expect(model.get('value')).to.eql(date); + }); + + it('should serialize as expected', async () => { + const state_in = { + value: { + year: 2002, + month: 2, + date: 20, + hours: 20, + minutes: 2, + seconds: 20, + milliseconds: 2 + } + }; + + const model = await createTestModelFromSerialized( + NaiveDatetimeModel, + state_in + ); + model.widget_manager.register_model( + model.model_id, + Promise.resolve(model) + ); + + const state_out = await (model.widget_manager as DummyManager).get_state(); + const models = Object.keys(state_out.state).map( + k => state_out.state[k].state + ); + expect(models.length).to.eql(1); + expect(models[0]._model_name).to.be('NaiveDatetimeModel'); + expect(models[0].value).to.eql(state_in.value); + }); + + it('should deserialize to Date object', async () => { + const state_in = { + value: { + year: 2002, + month: 2, + date: 20, + hours: 20, + minutes: 2, + seconds: 20, + milliseconds: 2 + } + }; + + const model = await createTestModelFromSerialized( + NaiveDatetimeModel, + state_in + ); + expect(model.get('value')).to.eql(new Date(2002, 2, 20, 20, 2, 20, 2)); + }); + + it('should deserialize null', async () => { + const state_in = { value: null }; + + const model = await createTestModelFromSerialized( + NaiveDatetimeModel, + state_in + ); + expect(model.get('value')).to.be.a('null'); + }); + + it('should deserialize undefined', async () => { + const state_in = {}; + const model = await createTestModelFromSerialized( + NaiveDatetimeModel, + state_in + ); + expect(model.get('value')).to.be.a('null'); + }); + }); }); diff --git a/packages/schema/jupyterwidgetmodels.latest.json b/packages/schema/jupyterwidgetmodels.latest.json index 06eac0adba..62f705ad32 100644 --- a/packages/schema/jupyterwidgetmodels.latest.json +++ b/packages/schema/jupyterwidgetmodels.latest.json @@ -368,9 +368,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -426,10 +424,7 @@ { "default": [], "help": "List of widget children", - "items": { - "type": "reference", - "widget": "Widget" - }, + "items": { "type": "reference", "widget": "Widget" }, "name": "children", "type": "array" }, @@ -478,9 +473,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -588,9 +581,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -655,18 +646,8 @@ "type": "reference", "widget": "Layout" }, - { - "default": 100.0, - "help": "Max value", - "name": "max", - "type": "float" - }, - { - "default": 0.0, - "help": "Min value", - "name": "min", - "type": "float" - }, + { "default": 100.0, "help": "Max value", "name": "max", "type": "float" }, + { "default": 0.0, "help": "Min value", "name": "min", "type": "float" }, { "allow_none": true, "default": null, @@ -718,9 +699,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -785,18 +764,8 @@ "type": "reference", "widget": "Layout" }, - { - "default": 100, - "help": "Max value", - "name": "max", - "type": "int" - }, - { - "default": 0, - "help": "Min value", - "name": "min", - "type": "int" - }, + { "default": 100, "help": "Max value", "name": "max", "type": "int" }, + { "default": 0, "help": "Min value", "name": "min", "type": "int" }, { "default": 1, "help": "Minimum step to increment the value", @@ -824,12 +793,7 @@ "name": "tooltip", "type": "string" }, - { - "default": 0, - "help": "Int value", - "name": "value", - "type": "int" - } + { "default": 0, "help": "Int value", "name": "value", "type": "int" } ], "model": { "module": "@jupyter-widgets/controls", @@ -847,9 +811,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -899,10 +861,7 @@ { "default": [], "help": "List of widget children", - "items": { - "type": "reference", - "widget": "Widget" - }, + "items": { "type": "reference", "widget": "Widget" }, "name": "children", "type": "array" }, @@ -944,9 +903,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -1119,9 +1076,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -1230,9 +1185,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -1341,9 +1294,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -1417,9 +1368,7 @@ { "default": [], "help": "Dropdown options for the combobox", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "options", "type": "array" }, @@ -1473,9 +1422,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -1559,9 +1506,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -1651,9 +1596,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -1696,20 +1639,14 @@ { "default": [], "help": "The axes on the gamepad.", - "items": { - "type": "reference", - "widget": "Axis" - }, + "items": { "type": "reference", "widget": "Axis" }, "name": "axes", "type": "array" }, { "default": [], "help": "The buttons on the gamepad.", - "items": { - "type": "reference", - "widget": "Button" - }, + "items": { "type": "reference", "widget": "Button" }, "name": "buttons", "type": "array" }, @@ -1781,9 +1718,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -1868,9 +1803,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -1949,13 +1882,8 @@ "name": "step", "type": ["int", "string"], "union_attributes": [ - { - "type": "int" - }, - { - "enum": ["any"], - "type": "string" - } + { "type": "int" }, + { "enum": ["any"], "type": "string" } ] }, { @@ -2003,9 +1931,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -2242,9 +2168,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -2269,9 +2193,7 @@ { "default": [], "help": "The labels for the options.", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_options_labels", "type": "array" }, @@ -2357,9 +2279,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -2493,9 +2413,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -2647,9 +2565,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -2710,18 +2626,8 @@ "type": "reference", "widget": "Layout" }, - { - "default": 100.0, - "help": "Max value", - "name": "max", - "type": "float" - }, - { - "default": 0.0, - "help": "Min value", - "name": "min", - "type": "float" - }, + { "default": 100.0, "help": "Max value", "name": "max", "type": "float" }, + { "default": 0.0, "help": "Min value", "name": "min", "type": "float" }, { "default": "horizontal", "enum": ["horizontal", "vertical"], @@ -2773,9 +2679,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -2840,18 +2744,8 @@ "type": "reference", "widget": "Layout" }, - { - "default": 100.0, - "help": "Max value", - "name": "max", - "type": "float" - }, - { - "default": 0.0, - "help": "Min value", - "name": "min", - "type": "float" - }, + { "default": 100.0, "help": "Max value", "name": "max", "type": "float" }, + { "default": 0.0, "help": "Min value", "name": "min", "type": "float" }, { "default": "horizontal", "enum": ["horizontal", "vertical"], @@ -2921,9 +2815,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -2988,18 +2880,8 @@ "type": "reference", "widget": "Layout" }, - { - "default": 100.0, - "help": "Max value", - "name": "max", - "type": "float" - }, - { - "default": 0.0, - "help": "Min value", - "name": "min", - "type": "float" - }, + { "default": 100.0, "help": "Max value", "name": "max", "type": "float" }, + { "default": 0.0, "help": "Min value", "name": "min", "type": "float" }, { "default": "horizontal", "enum": ["horizontal", "vertical"], @@ -3069,9 +2951,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -3187,9 +3067,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -3239,10 +3117,7 @@ { "default": [], "help": "List of widget children", - "items": { - "type": "reference", - "widget": "Widget" - }, + "items": { "type": "reference", "widget": "Widget" }, "name": "children", "type": "array" }, @@ -3284,9 +3159,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -3336,10 +3209,7 @@ { "default": [], "help": "List of widget children", - "items": { - "type": "reference", - "widget": "Widget" - }, + "items": { "type": "reference", "widget": "Widget" }, "name": "children", "type": "array" }, @@ -3381,9 +3251,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -3486,9 +3354,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -3591,9 +3457,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -3695,9 +3559,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -3757,18 +3619,8 @@ "type": "reference", "widget": "Layout" }, - { - "default": 100, - "help": "Max value", - "name": "max", - "type": "int" - }, - { - "default": 0, - "help": "Min value", - "name": "min", - "type": "int" - }, + { "default": 100, "help": "Max value", "name": "max", "type": "int" }, + { "default": 0, "help": "Min value", "name": "min", "type": "int" }, { "default": "horizontal", "enum": ["horizontal", "vertical"], @@ -3797,12 +3649,7 @@ "name": "tooltip", "type": "string" }, - { - "default": 0, - "help": "Int value", - "name": "value", - "type": "int" - } + { "default": 0, "help": "Int value", "name": "value", "type": "int" } ], "model": { "module": "@jupyter-widgets/controls", @@ -3820,9 +3667,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -3887,18 +3732,8 @@ "type": "reference", "widget": "Layout" }, - { - "default": 100, - "help": "Max value", - "name": "max", - "type": "int" - }, - { - "default": 0, - "help": "Min value", - "name": "min", - "type": "int" - }, + { "default": 100, "help": "Max value", "name": "max", "type": "int" }, + { "default": 0, "help": "Min value", "name": "min", "type": "int" }, { "default": "horizontal", "enum": ["horizontal", "vertical"], @@ -3968,9 +3803,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -4035,18 +3868,8 @@ "type": "reference", "widget": "Layout" }, - { - "default": 100, - "help": "Max value", - "name": "max", - "type": "int" - }, - { - "default": 0, - "help": "Min value", - "name": "min", - "type": "int" - }, + { "default": 100, "help": "Max value", "name": "max", "type": "int" }, + { "default": 0, "help": "Min value", "name": "min", "type": "int" }, { "default": "horizontal", "enum": ["horizontal", "vertical"], @@ -4093,12 +3916,7 @@ "name": "tooltip", "type": "string" }, - { - "default": 0, - "help": "Int value", - "name": "value", - "type": "int" - } + { "default": 0, "help": "Int value", "name": "value", "type": "int" } ], "model": { "module": "@jupyter-widgets/controls", @@ -4116,9 +3934,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -4210,12 +4026,7 @@ "name": "tooltip", "type": "string" }, - { - "default": 0, - "help": "Int value", - "name": "value", - "type": "int" - } + { "default": 0, "help": "Int value", "name": "value", "type": "int" } ], "model": { "module": "@jupyter-widgets/controls", @@ -4233,9 +4044,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -4401,9 +4210,125 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, + "name": "_dom_classes", + "type": "array" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_model_module", + "type": "string" + }, + { + "default": "1.5.0", + "help": "", + "name": "_model_module_version", + "type": "string" + }, + { + "default": "NaiveDatetimeModel", + "help": "", + "name": "_model_name", + "type": "string" + }, + { + "default": "@jupyter-widgets/controls", + "help": "", + "name": "_view_module", + "type": "string" + }, + { + "default": "1.5.0", + "help": "", + "name": "_view_module_version", + "type": "string" + }, + { + "default": "DatetimeView", + "help": "", + "name": "_view_name", + "type": "string" + }, + { + "default": "", + "help": "Description of the control.", + "name": "description", + "type": "string" + }, + { + "default": false, + "help": "Enable or disable user changes.", + "name": "disabled", + "type": "bool" + }, + { + "default": "reference to new instance", + "help": "", + "name": "layout", + "type": "reference", + "widget": "Layout" + }, + { + "allow_none": true, + "default": null, + "help": "", + "name": "max", + "type": "Datetime" + }, + { + "allow_none": true, + "default": null, + "help": "", + "name": "min", + "type": "Datetime" + }, + { + "default": "reference to new instance", + "help": "Styling customizations", + "name": "style", + "type": "reference", + "widget": "DescriptionStyle" + }, + { + "allow_none": true, + "default": null, + "help": "Is widget tabbable?", + "name": "tabbable", + "type": "bool" + }, + { + "allow_none": true, + "default": null, + "help": "A tooltip caption.", + "name": "tooltip", + "type": "string" + }, + { + "allow_none": true, + "default": null, + "help": "", + "name": "value", + "type": "Datetime" + } + ], + "model": { + "module": "@jupyter-widgets/controls", + "name": "NaiveDatetimeModel", + "version": "1.5.0" + }, + "view": { + "module": "@jupyter-widgets/controls", + "name": "DatetimeView", + "version": "1.5.0" + } + }, + { + "attributes": [ + { + "default": [], + "help": "CSS classes applied to widget DOM element", + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -4518,9 +4443,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -4585,18 +4508,8 @@ "type": "reference", "widget": "Layout" }, - { - "default": 100, - "help": "Max value", - "name": "max", - "type": "int" - }, - { - "default": 0, - "help": "Min value", - "name": "min", - "type": "int" - }, + { "default": 100, "help": "Max value", "name": "max", "type": "int" }, + { "default": 0, "help": "Min value", "name": "min", "type": "int" }, { "default": false, "help": "Whether the control is currently playing.", @@ -4615,12 +4528,7 @@ "name": "show_repeat", "type": "bool" }, - { - "default": 1, - "help": "Increment step", - "name": "step", - "type": "int" - }, + { "default": 1, "help": "Increment step", "name": "step", "type": "int" }, { "default": "reference to new instance", "help": "Styling customizations", @@ -4642,12 +4550,7 @@ "name": "tooltip", "type": "string" }, - { - "default": 0, - "help": "Int value", - "name": "value", - "type": "int" - } + { "default": 0, "help": "Int value", "name": "value", "type": "int" } ], "model": { "module": "@jupyter-widgets/controls", @@ -4728,9 +4631,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -4755,9 +4656,7 @@ { "default": [], "help": "The labels for the options.", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_options_labels", "type": "array" }, @@ -4843,9 +4742,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -4870,9 +4767,7 @@ { "default": [], "help": "The labels for the options.", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_options_labels", "type": "array" }, @@ -4964,9 +4859,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -4991,9 +4884,7 @@ { "default": [], "help": "The labels for the options.", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_options_labels", "type": "array" }, @@ -5030,9 +4921,7 @@ { "default": [], "help": "Selected indices", - "items": { - "type": "int" - }, + "items": { "type": "int" }, "name": "index", "type": "array" }, @@ -5087,9 +4976,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -5114,9 +5001,7 @@ { "default": [], "help": "The labels for the options.", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_options_labels", "type": "array" }, @@ -5220,9 +5105,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -5247,9 +5130,7 @@ { "default": [], "help": "The labels for the options.", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_options_labels", "type": "array" }, @@ -5416,9 +5297,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -5474,10 +5353,7 @@ { "default": [], "help": "List of widget children", - "items": { - "type": "reference", - "widget": "Widget" - }, + "items": { "type": "reference", "widget": "Widget" }, "name": "children", "type": "array" }, @@ -5526,9 +5402,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -5584,10 +5458,7 @@ { "default": [], "help": "List of widget children", - "items": { - "type": "reference", - "widget": "Widget" - }, + "items": { "type": "reference", "widget": "Widget" }, "name": "children", "type": "array" }, @@ -5636,9 +5507,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -5753,9 +5622,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -5877,9 +5744,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -5958,13 +5823,8 @@ "name": "step", "type": ["float", "string"], "union_attributes": [ - { - "type": "float" - }, - { - "enum": ["any"], - "type": "string" - } + { "type": "float" }, + { "enum": ["any"], "type": "string" } ] }, { @@ -6012,9 +5872,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -6130,9 +5988,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -6157,9 +6013,7 @@ { "default": [], "help": "The labels for the options.", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_options_labels", "type": "array" }, @@ -6204,9 +6058,7 @@ { "default": [], "help": "Icons names for each button (FontAwesome names without the fa- prefix).", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "icons", "type": "array" }, @@ -6248,9 +6100,7 @@ { "default": [], "help": "Tooltips for each button.", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "tooltips", "type": "array" } @@ -6339,9 +6189,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -6391,10 +6239,7 @@ { "default": [], "help": "List of widget children", - "items": { - "type": "reference", - "widget": "Widget" - }, + "items": { "type": "reference", "widget": "Widget" }, "name": "children", "type": "array" }, @@ -6436,9 +6281,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -6547,9 +6390,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -6669,9 +6510,7 @@ { "default": [], "help": "CSS classes applied to widget DOM element", - "items": { - "type": "string" - }, + "items": { "type": "string" }, "name": "_dom_classes", "type": "array" }, @@ -6727,9 +6566,7 @@ { "default": [], "help": "The output messages synced from the frontend.", - "items": { - "type": "object" - }, + "items": { "type": "object" }, "name": "outputs", "type": "array" }, diff --git a/packages/schema/jupyterwidgetmodels.latest.md b/packages/schema/jupyterwidgetmodels.latest.md index 5545306c1c..500210303a 100644 Binary files a/packages/schema/jupyterwidgetmodels.latest.md and b/packages/schema/jupyterwidgetmodels.latest.md differ